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

Google에 많은 도움을 받았고 많은 해결책을 찾았지만 아무도 2012-12-31의 정확한 주 번호를 제공하지 않습니다. MSDN의 예조차도 ( 링크 )도 실패합니다.

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매개 변수입니다.

여기를 참조하십시오 :
https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=IT-IT&k=k(System.Globalization.CalendarWeekRule);k(TargetFrameworkMoniker-.NETFramework


답변

좋은 소식! 풀 요청 추가System.Globalization.ISOWeek.NET Core에 이 병합되었으며 현재 3.0 릴리스로 예정되어 있습니다. 바라지 않는 미래에 다른 .NET 플랫폼으로 전파되기를 바랍니다.

유형에는 다음과 같은 서명이 있으며 대부분의 ISO 주 요구 사항을 충족해야합니다.

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);
    }
}

소스 코드는 여기에서 찾을 수 있습니다 .

업데이트 :이 API는 2.1 버전의 .NET Standard 에도 포함 되었습니다 .


답변

정확한 ISO-8601 주 번호를 산출하는 .Net 문화가없는 것 같아서, 부분적으로 정확한 수정을 시도하는 대신 내장 주 결정을 우회하고 수동으로 계산을 수행하고 싶습니다. 결과.

내가 끝내었던 것은 다음 확장 방법입니다.

/// <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;
}

우선 ((int)date.DayOfWeek + 6) % 7), 요일 번호를 결정합니다 (0 = 월요일, 6 = 일요일).

date.AddDays(-((int)date.DayOfWeek + 6) % 7) 요청 된 주 번호를 선행하는 월요일 날짜를 결정합니다.

3 일 후 목표 목요일이 있으며, 그 주가 몇 년인지 결정합니다.

연도 내 (0부터 시작) 일수를 7 (내림차순)로 나누면 연도에서 0으로 표시되는 주 번호를 얻습니다.

C #에서 정수 계산 결과는 내재적으로 반올림됩니다.


답변

.NET 3.0 이상에서는 ISOWeek.GetWeekOfDate-Method를 사용할 수 있습니다 .

연도 + 주 번호 형식의 연도 DateTime는 연도 경계를 넘는 주 때문에 연도와 다를 수 있습니다 .


답변

il_guru 에서 위 코드의 C #에서 Powershell 포트로 :

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
}