WEEK_OF_YEAR在不同的机器上不一致 [英] WEEK_OF_YEAR inconsistent on different machines

查看:917
本文介绍了WEEK_OF_YEAR在不同的机器上不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:确定,我似乎找到一半的答案。如果我使用无参数getInstance创建了我的日历,我得到WEEK_OF_YEAR = 52.但是,如果我通过提供Local.getDefaul()到getInstance创建它,我得到WEEK_OF_YEAR = 1。完全没有想到这...需要重新阅读Google日历文档。



从时间戳构建日历,对应于星期六,2011年1月1日00:00:00



使用java.util.Date,Calendar和TimeZone的同一个代码在不同的机器(具有相同的区域设置)上表现不同。日历中的所有字段都相同,除了WEEK_OF_YEAR。在我的机器上是52(我的两台机器上,实际上)。在我的同事的机器上它是1(这似乎是正确的)。

  import java.util.Date; 
import java.util.TimeZone;
import java.util.Calendar;
import java.util.Locale;

public class CalendarTest {

public static void main(String [] args){

Locale l = Locale.getDefault();
System.out.println(l);
Long d = new Long(1293840000000l);

日历c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone(UTC));
c.setTime(new Date(d));

System.out.println(c.toString());
}

..
语言环境是en_US,但日历是:

 > java.util.GregorianCalendar [time = 1293840000000,
areFieldsSet = true,
areAllFieldsSet = true,
lenient = true,
zone = sun.util.calendar.ZoneInfo [
id =UTC,
offset = 0,
dstSavings = 0,
useDaylight = false,
transitions = 0,lastRule = null
],
firstDayOfWeek = 2,
minimalDaysInFirstWeek = 4,
ERA = 1,
YEAR = 2011,
MONTH = 0,
WEEK_OF_YEAR = 52,
WEEK_OF_MONTH = 0,
DAY_OF_MONTH = 1,
DAY_OF_YEAR = 1,
DAY_OF_WEEK = 7,
DAY_OF_WEEK_IN_MONTH = 1,
AM_PM = 0,HOUR = 0,
HOUR_OF_DAY = 0,
MINUTE = 0,
SECOND = 0,
MILLISECOND = 0,
ZONE_OFFSET = 0,
DST_OFFSET = 0]

这可能会导致此WEEK_OF_YEAR不一致?

解决方案

firstDayOfWeek minimalDaysInFirstWeek



原来是一个功能,而不是一个错误。



您看到的不同行为的原因是在您的问题中显示的输出中报告的两个设置:




  • firstDayOfWeek

  • minimalDaysInFirstWeek



阅读类和子类的文档很重要:




  • 标准定义的行为,如我的其他答案。这可能是为什么这些设置是非默认在您的问题机器上的线索。



    示例代码



    让我们用一些代码演示这个。我们将使用问题的代码的修改版本。我们的代码在这里明确地设置了所讨论的变量。所以你可以在任何机器上运行这个例子,正常或问题。首先,我们强制使用默认情况下在美国Locale机器上找到的设置, 1 & 1 。然后我们使用问题 2 & 4

      Locale l = Locale .getDefault(); 
    System.out.println(l +\\\
    );
    Long d = new Long(1293840000000l);

    日历c = Calendar.getInstance();
    c.setTimeZone(TimeZone.getTimeZone(UTC));
    c.setTime(new Date(d));

    //运行Java 8 Update 11,Mac OS 10.8.5,Parallels 9中的虚拟机,在Mac上使用Mavericks进行托管。

    //强制使用在美国区域设置(使用Apple默认设置)的机器上找到的默认设置。
    c.setFirstDayOfWeek(1);
    c.setMinimalDaysInFirstWeek(1);
    //报告:WEEK_OF_YEAR = 1
    System.out.println(默认US设置:\\\
    + c.toString()+\\\
    );

    //使用报告的设置(符合ISO 8601 Week定义)。
    c.setFirstDayOfWeek(2);
    c.setMinimalDaysInFirstWeek(4);
    //报告:WEEK_OF_YEAR = 52
    System.out.println(报告的设置(ISO 8601):\\\
    + c.toString()+\\\
    );

    运行时...

      en_US 

    默认US设置:
    java.util.GregorianCalendar [time = 1293840000000,areFieldsSet = true,areAllFieldsSet = true,lenient = true,zone = sun.util.calendar.ZoneInfo [id =UTC,offset = 0,dstSavings = 0,useDaylight = false,transitions = 0,lastRule = null],firstDayOfWeek = 1,minimalDaysInFirstWeek = 1,ERA = 1 ,YEAR = 2011,MONTH = 0,WEEK_OF_YEAR = 1,WEEK_OF_MONTH = 1,DAY_OF_MONTH = 1,DAY_OF_YEAR = 1,DAY_OF_WEEK = 7,DAY_OF_WEEK_IN_MONTH = 1,AM_PM = 0,HOUR = 0,HOUR_OF_DAY = 0,MINUTE = 0,SECOND = 0,MILLISECOND = 0,ZONE_OFFSET = 0,DST_OFFSET = 0]

    报告的设置(ISO 8601):
    java.util.GregorianCalendar [time = 1293840000000,areFieldsSet = true,areAllFieldsSet = true,lenient = true,zone = sun.util.calendar.ZoneInfo [id =UTC,offset = 0,dstSavings = 0,useDaylight = false,transitions = 0,lastRule = null],firstDayOfWeek = 2,minimalDaysInFirstWeek = 4 ,ERA = 1,YEAR = 2011,MONTH = 0,WEEK_OF_YEAR = 52,WEEK_OF_MONTH = 0,DAY_OF_MONTH = 1,DAY_OF_YEAR = 1,DAY_OF_WEEK = 7,DAY_OF_WEEK_IN_MONTH = 1,AM_PM = 0,HOUR = 0,HOUR_OF_DAY = 0,MINUTE = 0,SECOND = 0,MILLISECOND = 0,ZONE_OFFSET = 0,DST_OFFSET = 0]





    使用 ISO 8601标准星期

    Update: ok, I seem to have found half the answer. If I created my Calendar with a no-argument getInstance, I get WEEK_OF_YEAR = 52. However, if I create it with supplying Local.getDefaul() to the getInstance, I get WEEK_OF_YEAR = 1. Totally didn't expect this... need to re-read the Calendar docs, I guess.

    Building a Calendar from a timestamp, which corresponds to Sat, 01 Jan 2011 00:00:00 GMT.

    The same code, using java.util.Date, Calendar and TimeZone, is behaving differently on different machines (with the same locale); all the fields in the Calendar are the same, except WEEK_OF_YEAR. On my machine it is 52 (on two of my machines, actually). On my coworker's machines it's 1 (which seems to be correct).

    import java.util.Date;
    import java.util.TimeZone;
    import java.util.Calendar;
    import java.util.Locale;
    
    public class CalendarTest {
    
        public static void main(String[] args) {
    
            Locale l = Locale.getDefault();
            System.out.println(l);
            Long d = new Long(1293840000000l);
    
            Calendar c = Calendar.getInstance();
            c.setTimeZone(TimeZone.getTimeZone("UTC"));
            c.setTime(new Date(d));
    
            System.out.println(c.toString());
    }
    

    .. locale is en_US, but Calendar is:

    >java.util.GregorianCalendar[time=1293840000000,
    areFieldsSet=true,
    areAllFieldsSet=true,
    lenient=true,
    zone=sun.util.calendar.ZoneInfo[
    id="UTC",
    offset=0,
    dstSavings=0,
    useDaylight=false,
    transitions=0,lastRule=null
    ],
    firstDayOfWeek=2,
    minimalDaysInFirstWeek=4,
    ERA=1,
    YEAR=2011,
    MONTH=0,
    WEEK_OF_YEAR=52,
    WEEK_OF_MONTH=0,
    DAY_OF_MONTH=1,
    DAY_OF_YEAR=1,
    DAY_OF_WEEK=7,
    DAY_OF_WEEK_IN_MONTH=1,
    AM_PM=0,HOUR=0,
    HOUR_OF_DAY=0,
    MINUTE=0,
    SECOND=0,
    MILLISECOND=0,
    ZONE_OFFSET=0,
    DST_OFFSET=0]
    

    What might be causing this WEEK_OF_YEAR inconsistency?

    解决方案

    firstDayOfWeek & minimalDaysInFirstWeek

    Turns out to be a feature, not a bug.

    The cause of the different behaviors you see is two settings reported in your output shown in the Question:

    • firstDayOfWeek
    • minimalDaysInFirstWeek

    It’s important to read the doc for both the class and subclass:

    The second doc explains in detail how those two settings listed above are crucial to determining a localized week.

    Calendar

    Note the calendar. The first day of 2011 is a Saturday. The second of the month is a Sunday, and Sunday is the default start-of-week for United States.

    On a Mac OS X computer set to United States locale, these settings are both 1. If the minimum days needed is 1, then the First lands on a localized Week 1. Java reports this.

    But on your reported problem machine, these settings are 2 and 4, respectively. I don't know how you got these settings altered from the usual defaults, but you did.

    • firstDayOfWeek | 1 versus 2 (Sunday versus Monday)
    • minimalDaysInFirstWeek | 1 versus 4

    The minimum of 4 days means that the First does not qualify as a week in the new year. So it is week 52 of the previous year (2010). The first week of 2011 is January 2, 2011 through January 8.

    So the behavior you are seeing matches expectations given the documentation for the java.util.Calendar class in Java 7. The mystery is how did those settings get changed away from the default on your problem machine?

    ISO 8601

    By the way, the doc mentions that settings of 2 & 4 gives you the behavior defined by the ISO 8601 standard, as mentioned in my other answer. That may be the clue as to why these settings are non-default on your problem machine. Someone, a sysadmin or programmer, may be trying to get standard behavior rather than localized behavior.

    Example Code

    Let's demonstrate this with some code. We’ll use a modified version of the code from the Question. Our code here explicitly sets the variables at issue. So you can run this example on any of your machines, normal or problem. First we force the use of the settings found by default on a US Locale machine, 1 & 1. Then we use the settings reported in the Question, 2 & 4.

    Locale l = Locale.getDefault();
    System.out.println( l + "\n" );
    Long d = new Long( 1293840000000l );
    
    Calendar c = Calendar.getInstance();
    c.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
    c.setTime( new Date( d ) );
    
    // Running Java 8 Update 11, Mac OS 10.8.5, virtual machine in Parallels 9, hosted on Mac with Mavericks.
    
    // Force the use of default settings found on a machine set for United States locale (using Apple defaults).
    c.setFirstDayOfWeek( 1 );
    c.setMinimalDaysInFirstWeek( 1 );
    // Reports: WEEK_OF_YEAR=1
    System.out.println( "Default US settings:\n" + c.toString() + "\n" );
    
    // Using reported settings (Coincides with ISO 8601 Week definition).
    c.setFirstDayOfWeek( 2 );
    c.setMinimalDaysInFirstWeek( 4 );
    // Reports: WEEK_OF_YEAR=52
    System.out.println( "Reported settings (ISO 8601):\n" + c.toString() + "\n" );
    

    When run…

    en_US
    
    Default US settings:
    java.util.GregorianCalendar[time=1293840000000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2011,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=1,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]
    
    Reported settings (ISO 8601):
    java.util.GregorianCalendar[time=1293840000000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2011,MONTH=0,WEEK_OF_YEAR=52,WEEK_OF_MONTH=0,DAY_OF_MONTH=1,DAY_OF_YEAR=1,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]
    

    Moral Of The Story

    Use ISO 8601 standard weeks!

    这篇关于WEEK_OF_YEAR在不同的机器上不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆