Programing

주어진 날짜의 정확한 주 번호를 얻으십시오

lottogame 2020. 5. 13. 07:58
반응형

주어진 날짜의 정확한 주 번호를 얻으십시오


Google에 많은 도움을 받았고 많은 해결책을 찾았지만 그 중 어느 것도 2012-12-31의 정확한 주 번호를 제공하지 않습니다. MSDN의 예제 ( link )도 실패합니다.

2012-12-31은 월요일이므로 1 주가되어야하지만 시도한 모든 방법은 53을 제공합니다. 다음은 시도한 방법 중 일부입니다.

MDSN 라이브러리에서 :

DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
Calendar cal = dfi.Calendar;

return cal.GetWeekOfYear(date, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);

해결책 2 :

return new GregorianCalendar(GregorianCalendarTypes.Localized).GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

해결책 3 :

CultureInfo ciCurr = CultureInfo.CurrentCulture;
int weekNum = ciCurr.Calendar.GetWeekOfYear(dtPassed, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return weekNum;

최신 정보

다음 방법은 날짜가 2012-12-31 일 때 실제로 1을 반환합니다. 즉, 내 문제는 내 방법이 ISO-8601 표준을 따르지 않았다는 것입니다.

// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
    // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
    // be the same week# as whatever Thursday, Friday or Saturday are,
    // and we always get those right
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    // Return the week of our adjusted day
    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}

MSDN 페이지에 언급 된 바와 같이 ISO8601 주와 .Net 주 번호 사이에는 약간의 차이가 있습니다.

더 자세한 설명을 보려면 MSDN 블로그에서이 기사를 참조하십시오. " Microsoft .Net의 ISO 8601 주간 형식 "

간단히 말해서, .Net은 몇 주에 걸쳐 몇 주 동안 분할 될 수 있지만 ISO 표준은 그렇지 않습니다. 이 기사에는 연도의 마지막 주에 올바른 ISO 8601 주 번호를 얻는 간단한 기능도 있습니다.

업데이트 다음 방법은 실제로 2012-12-31ISO 8601 (예 : 독일)에서 1을 반환합니다 .

// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
    // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
    // be the same week# as whatever Thursday, Friday or Saturday are,
    // and we always get those right
    DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    // Return the week of our adjusted day
    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
} 

1 년에 52 주 이상이있을 수 있습니다. 매년 52 주 전체 + 1 또는 +2 (윤년)이 추가됩니다. 그들은 53 주를 보충합니다.

  • 52 주 * 7 일 = 364 일

따라서 매년 최소한 하루가 더 있습니다. 윤년 2 년. 이 추가 일수는 별도의 주 단위로 계산됩니까?

몇 주가 실제로 시작하는지에 따라 다릅니다. 이것을 2012 년에 고려해 봅시다.

  • 미국 (일요일-> 토요일) : 52 주 + 2012-12-30 및 2012-12-31의 짧은 2 일 주. 총 53 주가 소요됩니다. 올해 마지막 2 일 (일요일 + 월요일)은 짧은 주를 구성합니다.

현재 문화권 설정을 확인하여 주중 첫날로 사용되는 것을 확인하십시오.

보시다시피 결과적으로 53을 얻는 것이 정상입니다.

  • 유럽 ​​(월요일-> 일요일) : 1 월 2dn (2012-1-2)이 첫 번째 월요일이므로 첫 주가 시작됩니다. 1 월 1 일 주 번호를 요청하면 지난 주 2011 년의 일부로 간주되므로 52가 다시 표시됩니다.

54 주가있을 수도 있습니다. 1 월 1 일과 12 월 31 일이 별도의 주로 취급되는 28 년마다 발생합니다. 윤년이어야합니다.

예를 들어 2000 년에는 54 주가있었습니다. 1 월 1 일 (토)은 첫 1 주일이었고 12 월 31 일 (일)은 두 번째 1 주일이되었습니다.

var d = new DateTime(2012, 12, 31);
CultureInfo cul = CultureInfo.CurrentCulture;

var firstDayWeek = cul.Calendar.GetWeekOfYear(
    d,
    CalendarWeekRule.FirstDay,
    DayOfWeek.Monday);

int weekNum = cul.Calendar.GetWeekOfYear(
    d,
    CalendarWeekRule.FirstDay,
    DayOfWeek.Monday);

int year = weekNum == 52 && d.Month == 1 ? d.Year - 1 : d.Year;
Console.WriteLine("Year: {0} Week: {1}", year, weekNum);

인쇄 : 년 : 2012 주 : 54

위의 예에서 CalendarWeekRule을 FirstFullWeek 또는 FirstFourDayWeek로 변경하면 53이 다시 표시됩니다. 독일을 다루는 월요일부터 시작일을 유지합시다.

따라서 53 주차는 2012-12-31 월요일에 시작하여 하루가 지난 후에 중단됩니다.

53이 정답입니다. 시도하고 싶다면 문화를 독일로 바꾸십시오.

CultureInfo cul = CultureInfo.GetCultureInfo("de-DE");

이게 방법이야:

public int GetWeekNumber()
{
    CultureInfo ciCurr = CultureInfo.CurrentCulture;
    int weekNum = ciCurr.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
    return weekNum;
}

가장 중요한 것은 CalendarWeekRule매개 변수입니다.

See here: https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=IT-IT&k=k(System.Globalization.CalendarWeekRule);k(TargetFrameworkMoniker-.NETFramework


Since there doesn't seem to be a .Net-culture that yields the correct ISO-8601 week number, I'd rather bypass the built-in week determination altogether, and do the calculation manually, instead of attempting to correct a partially correct result.

What I ended up with is the following extension method:

/// <summary>
/// Converts a date to a week number.
/// ISO 8601 week 1 is the week that contains the first Thursday that year.
/// </summary>
public static int ToIso8601Weeknumber(this DateTime date)
{
    var thursday = date.AddDays(3 - date.DayOfWeek.DayOffset());
    return (thursday.DayOfYear - 1) / 7 + 1;
}

/// <summary>
/// Converts a week number to a date.
/// Note: Week 1 of a year may start in the previous year.
/// ISO 8601 week 1 is the week that contains the first Thursday that year, so
/// if December 28 is a Monday, December 31 is a Thursday,
/// and week 1 starts January 4.
/// If December 28 is a later day in the week, week 1 starts earlier.
/// If December 28 is a Sunday, it is in the same week as Thursday January 1.
/// </summary>
public static DateTime FromIso8601Weeknumber(int weekNumber, int? year = null, DayOfWeek day = DayOfWeek.Monday)
{
    var dec28 = new DateTime((year ?? DateTime.Today.Year) - 1, 12, 28);
    var monday = dec28.AddDays(7 * weekNumber - dec28.DayOfWeek.DayOffset());
    return monday.AddDays(day.DayOffset());
}

/// <summary>
/// Iso8601 weeks start on Monday. This returns 0 for Monday.
/// </summary>
private static int DayOffset(this DayOfWeek weekDay)
{
    return ((int)weekDay + 6) % 7;
}

First of all, ((int)date.DayOfWeek + 6) % 7) determines the weekday number, 0=monday, 6=sunday.

date.AddDays(-((int)date.DayOfWeek + 6) % 7) determines the date of the monday preceiding the requested week number.

Three days later is the target thursday, which determines what year the week is in.

If you divide the (zero based) day-number within the year by seven (round down), you get the (zero based) week number in the year.

In c#, integer calculation results are round down implicitly.


Good news! A pull request adding System.Globalization.ISOWeek to .NET Core was just merged and is currently slated for the 3.0 release. Hopefully it will propagate to the other .NET platforms in a not-too-distant future.

The type has the following signature, which should cover most ISO week needs:

namespace System.Globalization
{
    public static class ISOWeek
    {
        public static int GetWeekOfYear(DateTime date);
        public static int GetWeeksInYear(int year);
        public static int GetYear(DateTime date);
        public static DateTime GetYearEnd(int year);
        public static DateTime GetYearStart(int year);
        public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek);
    }
}

You can find the source code here.

UPDATE: These APIs have also been included in the 2.1 version of .NET Standard.


C# to Powershell port from code above from il_guru:

function GetWeekOfYear([datetime] $inputDate)
{
   $day = [System.Globalization.CultureInfo]::InvariantCulture.Calendar.GetDayOfWeek($inputDate)
   if (($day -ge [System.DayOfWeek]::Monday) -and ($day -le [System.DayOfWeek]::Wednesday))
   {
      $inputDate = $inputDate.AddDays(3)
   }

   # Return the week of our adjusted day
   $weekofYear = [System.Globalization.CultureInfo]::InvariantCulture.Calendar.GetWeekOfYear($inputDate, [System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [System.DayOfWeek]::Monday)
   return $weekofYear
}

The easiest way to determine the week number ISO 8601 style using c# and the DateTime class.

Ask this: the how-many-eth thursday of the year is the thursday of this week. The answer equals the wanted week number.

var dayOfWeek = (int)moment.DayOfWeek;
// Make monday the first day of the week
if (--dayOfWeek < 0)
    dayOfWeek = 6;
// The whole nr of weeks before this thursday plus one is the week number
var weekNumber = (moment.AddDays(3 - dayOfWeek).DayOfYear - 1) / 7 + 1;

var cultureInfo = CultureInfo.CurrentCulture;
var calendar = cultureInfo.Calendar;

var calendarWeekRule = cultureInfo.DateTimeFormat.CalendarWeekRule;
var firstDayOfWeek = cultureInfo.DateTimeFormat.FirstDayOfWeek;
var lastDayOfWeek = cultureInfo.LCID == 1033 //En-us
                    ? DayOfWeek.Saturday
                    : DayOfWeek.Sunday;

var lastDayOfYear = new DateTime(date.Year, 12, 31);

var weekNumber = calendar.GetWeekOfYear(date, calendarWeekRule, firstDayOfWeek);

 //Check if this is the last week in the year and it doesn`t occupy the whole week
return weekNumber == 53 && lastDayOfYear.DayOfWeek != lastDayOfWeek 
       ? 1  
       : weekNumber;

It works well both for US and Russian cultures. ISO 8601 also will be correct, `cause Russian week starts at Monday.


Here is an extension version and nullable version of il_guru's answer.

Extension:

public static int GetIso8601WeekOfYear(this DateTime time)
{
    var day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
    if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
    {
        time = time.AddDays(3);
    }

    return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}

Nullable:

public static int? GetIso8601WeekOfYear(this DateTime? time)
{
    return time?.GetIso8601WeekOfYear();
}

Usages:

new DateTime(2019, 03, 15).GetIso8601WeekOfYear(); //returns 11
((DateTime?) new DateTime(2019, 03, 15)).GetIso8601WeekOfYear(); //returns 11
((DateTime?) null).GetIso8601WeekOfYear(); //returns null

The question is: How do you define if a week is in 2012 or in 2013? Your supposition, I guess, is that since 6 days of the week are in 2013, this week should be marked as the first week of 2013.

Not sure if this is the right way to go. That week started on 2012 (On monday 31th Dec), so it should be marked as the last week of 2012, therefore it should be the 53rd of 2012. The first week of 2013 should start on monday the 7th.

Now, you can handle the particular case of edge weeks (first and last week of the year) using the day of week information. It all depends on your logic.


  DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
  DateTime date1 = new DateTime(2011, 1, 1);
  Calendar cal = dfi.Calendar;

  Console.WriteLine("{0:d}: Week {1} ({2})", date1, 
                    cal.GetWeekOfYear(date1, dfi.CalendarWeekRule, 
                                      dfi.FirstDayOfWeek),
                    cal.ToString().Substring(cal.ToString().LastIndexOf(".") + 1));      

A year has 52 weeks and 1 day or 2 in case of a lap year (52 x 7 = 364). 2012-12-31 would be week 53, a week that would only have 2 days because 2012 is a lap year.

참고URL : https://stackoverflow.com/questions/11154673/get-the-correct-week-number-of-a-given-date

반응형