java获取星期几是不准确的

时间:2011-01-10 10:10:51

标签: java date

我正在尝试确定一周的哪一天是该月的第一天,但​​出于某种原因,它并没有让我回到正确的一周。

以下是我的代码:

CalendarMonth[] months = CalendarUtils.constructMonthViewArray(new GregorianCalendar());


    public static CalendarMonth[] constructMonthViewArray(Calendar cal) {
        CalendarMonth[] months = new CalendarMonth[CALENDAR_GRID_SIZE];


        int year = cal.get(cal.YEAR);
        int month = cal.get(cal.MONTH);;
        // calculate how many days in the month
        int numOfDays = getNumOfDaysInMonth(cal);
        // calculate what day(mon-sunday) is the 1st of the month
        int firstDayOfMonth = getFirstDayOfMonth(cal);



private static int getFirstDayOfMonth(Calendar cal) {
        int firstDay = cal.get(Calendar.DAY_OF_WEEK);

        Log.d(TAG, "");

        // decrement it because our array deals with values 0-6(indexes)
        firstDay--;


        if (firstDay == 0) {
            firstDay = 6;
        } else {
            // decrement again so that the days start from 0.
            firstDay--;
        }
        return firstDay;
    }

来自“int firstDay = cal.get(Calendar.DAY_OF_WEEK);”的行没有给我正确的一周中的每一天,并返回值2,以获得本月的第一天(2011年1月),当月的第一天是星期六(7)。

我错过了什么吗?我已经调试并检查了cal变量设置的月份,年份和日期,它确实表明今天的日期已更正,但是当我得到星期几时它没有得到值7。

3 个答案:

答案 0 :(得分:11)

我无法重现您所看到的问题。正如迈克尔所说,有很多代码没有向我们展示,但Calendar.getDayOfWeek绝对有效:

import java.util.*;

public class Test {
    public static void main(String[] args) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(2011, 0, 1); // 0 = January
        System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // Prints 7
    }
}

您是否忘记java.util.Calendar中的月份是0?

如果您可以制作类似的简短但完整的节目,以显示一周的错误日期,请发布。

你在firstDay内递减getFirstDayOfMonth 两次的事实似乎有点奇怪,以及它并没有真正反映方法名称的事实(正如迈克尔所说)。

最后,我不断推荐Java日期/时间处理:如果您可能使用Joda Time而不是java.util.Calendar,请执行此操作。这是一个更好,更好的API。

答案 1 :(得分:0)

getFirstDayOfMonth()的代码似乎没有按照方法名称的说明去做 - 但要真正理解发生了什么,我们需要查看所涉及的所有代码,尤其是日历初始化的方式和getNumOfDaysInMonth的代码()

要记住的一件事:根据getFirstDayOfWeek()

,一周中的第一天取决于区域设置

答案 2 :(得分:0)

TL;博士

从可怕的遗留类(CalendarGregorianCalendar等)转换为现代 java.time 类(ZonedDateTimeLocalDate,等等。)。然后获取星期几的对象,并要求它自动本地化当天的那一天的名称。

(GregorianCalendar) myJavaUtilCalendar   // Cast your `Calendar` to `GregorianCalendar` assuming it actually is one.
.toZonedDateTime()                       // Convert from legacy class to modern class.
.toLocalDate()                           // Extract date-only object, without time-of-day and without time zone.
.with(                                   // Adjust to another date by calling `TemporalAdjuster` implementation such as are found in `TemporalAdjusters` class.
    TemporalAdjusters.firstDayOfMonth()  // Adjust to the first day of the month.
)                                        // Returns another `LocalDate` object, for the first of the month.
.getDayOfWeek()                          // Obtain a `DayOfWeek` enum object, one of seven pre-defined objects representing each day of the week.
.getDisplayName(                         // Automatically localize.
    TextStyle.FULL ,                     // Specify how long or abbreviated.
    Locale.CANADA_FRENCH                 // Or `Locale.US` etc. to specify the human language and cultural norms to use in localizing.
)                                        // Returns text in a `String` such as “Monday” or “lundi”.

java.time

java.util.Calendar / .Date和相关的类是一个令人困惑的混乱,因为你已经学到了很多东西。

现代方法使用 java.time 类。

转换

如果以java.util.Calendar对象开头,请转换为java.time。

InstantUTC中时间轴上的一个时刻。

Instant instant = myJavaUtilCalendarObject.toInstant();

申请时区以获取日期以获得星期几。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );

请注意,时区对于确定日期(以及因此星期几)至关重要。 “今天”与世界各地同时发生的日期不同。例如,在巴黎,新的一天比蒙特利尔更早出现。

每月的第一天

让我们通过拨打withDayOfMonth来转到本月的第一天。

ZonedDateTime zdtFirstOfMonth = zdt.withDayOfMonth(1);

请注意,将日期时间移至月初是有问题的。夏令时(DST)等异常可能产生惊人的效果。阅读文档,以便了解行为。

DayOfWeek

对于星期几,请使用名称良好的DayOfWeek enum

DayOfWeek dayOfWeek = zdtFirstOfMonth.getDayOfWeek();

我建议传递此枚举的实例而不是2,例如7int dayOfWeekNumber = dayOfWeek.getValue(); 等。但如果您坚持,则可以提取整数。

String output = dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH );  // Or Locale.ENGLISH

要获取星期几名称的字符串,让java.time通过magic number方法生成本地化的字符串。

java.sql.*

关于 java.time

getDisplayName框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.Date和& Calendar

现在位于SimpleDateFormatJoda-Time项目建议迁移到maintenance mode类。

要了解详情,请参阅java.time。并搜索Stack Overflow以获取许多示例和解释。规范是Oracle Tutorial

您可以直接与数据库交换 java.time 对象。使用符合JSR 310或更高版本的JDBC driver。不需要字符串,不需要where类。

从哪里获取java.time类?

How to use ThreeTenABP…项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如ThreeTen-ExtraIntervalYearWeekYearQuarter