• ISO 8601 Week of Year format in Microsoft .Net


    Several people have noticed that Calendar.GetWeekOfYear() is almost like the ISO 8601 week when passed CalendarWeekRule.FirstFourDayWeek and DayOfWeek.Monday, however it is a little bit different.  Specifically ISO 8601 always has 7 day weeks.  If the first partial week of a year doesn't contain Thursday, then it is counted as the last week of the previous year.  Likewise, if the last week of the previous year doesn't contain Thursday then its treated like the first week of the next year.  GetWeekOfYear() has the first behavior, but not the second.  Ie:

    DateDayGetWeekOfYearISO 8601 Week
    12/31/2000 Sunday 52 of 2000 52 of 2000
    1/1/2001 Monday 1 of 2001 1 of 2001
    1/1/2005 Saturday 53 of 2004 53 of 2004
    12/31/2007 Monday 53 of 2007 1 of 2008

    Notice that the ISO 8601 week at the end of 2007 is different than the GetWeekOfYear() week.  For GetWeekOfYear(), both the last week and the first week have fewer than 7 days.  Also notice that even though its a 2007 date, its considered the first week of 2008.  Similarly the first day of 2005 is considered to be the last week of 2004 by either method.

    A simple workaround to consistently get the ISO 8601 week is to realize that consecutive days Monday through Sunday in ISO 8601 weeks all have the same week #.  So Monday has the same week # as Thursday.  Since Thursday is the critical day for determining when the week starts each year my solution is to add 3 days if the day is Monday, Tuesday or Wednesday.  The adjusted days are still in the same week, and use values that GetWeekOfYear and ISO 8601 agree on.

    Note that if the requirement is to compute a date in the 2004W536 form, the code will still have to detect that a week 53 in January means that we need to decrement the year by 1, and a week 1 in December requires incrementing the year by 1.

    Here's my example.  I made this a complete program, however GetIso8601WeekOfYear() is the worker function.  I used a static calendar, which probably isn't necessary.  Bala pointed out that one could derive a class from GregorianCalendar and override GetWeekOfYear(), but I'm not sure what the repercussions of using such a calendar elsewhere would be.  You can try it if you want, but for now this sample is just a simple static method.  Main is just here to run through a bunch of days and show when the week calculations differ. 

     1 using System;
     2 using System.Globalization;
     3 
     4 class Test
     5 {
     6     // Need a calendar.  Culture's irrelevent since we specify start day of week
     7     private static Calendar cal = CultureInfo.InvariantCulture.Calendar;
     8     
     9     // This presumes that weeks start with Monday.
    10     // Week 1 is the 1st week of the year with a Thursday in it.
    11     public static int GetIso8601WeekOfYear(DateTime time)
    12     {
    13         // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
    14         // be the same week# as whatever Thursday, Friday or Saturday are,
    15         // and we always get those right
    16         DayOfWeek day = cal.GetDayOfWeek(time);
    17         if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    18         {
    19             time = time.AddDays(3);
    20         }
    21         
    22         // Return the week of our adjusted day
    23         return cal.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
    24     }
    25     
    26     static void Main(string[] args)
    27     {
    28         // 1/1/1990 starts on a Monday
    29         DateTime dt = new DateTime(1990, 1, 1);
    30         Console.WriteLine("Starting at " + dt + " day: " + cal.GetDayOfWeek(dt) + " Week: " +GetIso8601WeekOfYear(dt));
    31 
    32         for (int i = 0; i < 100000; i++)
    33         {
    34             for (int days = 0; days < 7; dt=dt.AddDays(1), days++)
    35             {
    36                 if (GetIso8601WeekOfYear(dt) != cal.GetWeekOfYear(dt, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday))
    37                 {
    38                     Console.WriteLine("Iso Week " + GetIso8601WeekOfYear(dt) + 
    39                         " GetWeekOfYear: " + cal.GetWeekOfYear(dt, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday) + 
    40                         " Date: " + dt + " Day: " + cal.GetDayOfWeek(dt));
    41                 }
    42             }
    43         }
    44     }
    45 }
  • 相关阅读:
    javaScript的一些兼容性问题
    JavaScript的基本规范
    数组去重的方法有哪些?
    封装on emit off方法(observer)
    对数据进行单元格合并处理的函数
    判断浏览器的内核的函数方法
    bootstrap与vue的区别是什么?(十七)
    Redis介绍及使用(八)
    mysql常用sql语法
    idea使用maven下载jar包,出现证书校验问题问题,unable to find valid certification path to requested target
  • 原文地址:https://www.cnblogs.com/vayne/p/2783913.html
Copyright © 2020-2023  润新知