简体   繁体   English

在本地机器上日历不同的一年的第一周

[英]Calendar different first week of year on local machine

The below gives me different results (After) on my laptop than anywhere else.下面给出了我的笔记本电脑上与其他任何地方不同的结果(之后)。

private static void prindStartOfWeek() 
{
    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

    System.out.println(" --------- Before : " + cal.getTime());

    cal.set(Calendar.YEAR, 2015);
    cal.set(Calendar.WEEK_OF_YEAR, 1);
    cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    System.out.println(" --------- After : " + cal.getTime());
}

I'm using Eclipse Kepler , Windows 7 64bit , Java jdk1.7.0_65 .我正在使用Eclipse KeplerWindows 7 64bitJava jdk1.7.0_65 I tested on Eclipse Juno too and from cmd (executable jar) .我也在Eclipse Junocmd (executable jar) And the same applies.这同样适用。

I've tested the above code on my laptop and it prints我已经在我的笔记本电脑上测试了上面的代码并打印出来

 --------- Before : Fri Nov 20 14:04:07 EET 2015
 --------- After : Sun Jan 04 14:00:00 EET 2015

I've tested on Microsoft Server 2008 running Java 7 and it prints (which is the right value)我已经在运行Java 7 Microsoft Server 2008上进行了测试,它会打印(这是正确的值)

 --------- Before : Fri Nov 20 14:09:01 EET 2015
 --------- After : Sun Dec 28 14:00:00 EET 2014

I've tested here too and it prints我也在这里测试,它打印

 --------- Before : Fri Nov 20 10:54:40 UTC 2015
 --------- After : Sun Dec 28 00:00:00 UTC 2014

Does anyone know what might be going wrong?有谁知道可能会出什么问题? My laptop timezone is "Europe\\Athens", but it shouldn't matter I guess.我的笔记本电脑时区是“欧洲\\雅典”,但我猜应该没关系。

Moreover this was tested in another computer and it prints the right value此外,这是在另一台计算机上测试过的,它打印了正确的值

 --------- Before : Fri Nov 20 14:09:01 EET 2015
 --------- After : Sun Dec 28 14:00:00 EET 2014

getCalendar(TimeZone) "Gets a calendar using the specified time zone and default locale." getCalendar(TimeZone) "使用指定的时区和默认语言环境获取日历。"

As @Kartic notes in his comment above, in some places, Sunday is considered as first day of the week, and in other places, Monday is the first day of the week - this would be affected by your locale.正如@Kartic在上面的评论中指出的那样,在某些地方,星期日被视为一周的第一天,而在其他地方,星期一是一周的第一天 - 这会受到您所在地区的影响。

You probably have a different default locale between the machines on which you are running the code.您运行代码的机器之间可能有不同的默认语言环境。

tl;dr tl;博士

ZonedDateTime.now()                                     // Capture the current moment as seen through the lens of the wall-clock time used by the people of a particular region (time zone).
             .get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )  // Get the week number, with stable results per the ISO 8601 definition of a week that starts on a Monday and considers week # 1 to have the first Thursday of the calendar-year.

Locale语言环境

In the Calendar class, the meaning of a “week” changes by locale.Calendar类中,“周”的含义因地区而异。 If at runtime the JVM's current default Locale differs, the result of calculating weeks may differ.如果在运行时 JVM 的当前默认Locale不同,则计算周数的结果可能会有所不同。

For example, in the United States the first day of a week is Sunday.例如,在美国,一周的第一天是星期日。 But in much of Europe, and by ISO 8601 standard, the first day of the week is Monday.但在欧洲大部分地区,按照 ISO 8601 标准,一周的第一天是星期一。

That Calendar class is troublesome and confusing.那个Calendar类既麻烦又令人困惑。 And fortunately, now legacy, supplanted by the industry-leading java.time classes.幸运的是,现在是传统的,被业界领先的java.time类所取代。

java.time时间

Capture the current moment in UTC.以 UTC 格式捕获当前时刻。

Instant instant = Instant.now() ;

A time zone is crucial in determining a date.时区对于确定日期至关重要。 For any given moment, the date varies around the globe by zone.对于任何给定时刻,日期因地区而异。 For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec .例如,在法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔仍然是“昨天”。

If no time zone is specified, the JVM implicitly applies its current default time zone.如果未指定时区,JVM 会隐式应用其当前默认时区。 That default may change at any moment, so your results may vary.该默认值可能随时更改,因此您的结果可能会有所不同。 Better to specify your desired/expected time zone explicitly as an argument.最好将您想要/预期的时区明确指定为参数。

Specify a proper time zone name in the format of continent/region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland .continent/region的格式指定正确的时区名称,例如America/MontrealAfrica/CasablancaPacific/Auckland Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).永远不要使用ESTIST等 3-4 个字母的缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

If you want to use the JVM's current default time zone, ask for it and pass as an argument.如果您想使用 JVM 的当前默认时区,请询问它并作为参数传递。 If omitted, the JVM's current default is applied implicitly.如果省略,则隐式应用 JVM 的当前默认值。 Better to be explicit.最好是明确的。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Apply that ZoneId to get a ZonedDateTime object.应用该ZoneId以获取ZonedDateTime对象。

ZonedDateTime zdt = instant.atZone( z ) ;

Now get interrogate for the week-based year and week.现在查询基于周的年和周。 The IsoFields class provides objects through which we can get the week numbers per the ISO 8601 standard: IsoFields类提供了对象,我们可以通过这些对象获取符合 ISO 8601 标准的周数:

  • Week # 1 holds the first Thursday of the calendar-year第 1 周是日历年的第一个星期四
  • Monday is the first day of the year星期一是一年的第一天
  • A year has either 52 or 53 weeks.一年有 52 或 53 周。
  • The last/first few days of a year may lie in the previous/next week-based year.一年的最后/前几天可能位于前一周/下一周的年份。

Example.例子。

int yearIso = zdt.get( IsoFields.WEEK_BASED_YEAR ) ;
int weekIso = zdt.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;

TIP: Consider adding the ThreeTen-Extra library to your project to gain access to the YearWeek class.提示:考虑将ThreeTen-Extra库添加到您的项目中以访问YearWeek类。


About java.time关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于 Java 8 及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar ,和SimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial .要了解更多信息,请参阅Oracle 教程 And search Stack Overflow for many examples and explanations.并在 Stack Overflow 上搜索许多示例和解释。 Specification is JSR 310 .规范是JSR 310

Where to obtain the java.time classes?从哪里获得 java.time 类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目用额外的类扩展了 java.time。 This project is a proving ground for possible future additions to java.time.该项目是未来可能添加到 java.time 的试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more .您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM