7

特定の日付の年と週を返す必要があります。シンプルに聞こえます。しかし、2012 年の週 1 は 1 月 2 日から始まるため、2012-01-01 は 2011-52 を返す必要があります。

週を見つけるには、次を使用します。

GregorianCalendar calw = new GregorianCalendar(GregorianCalendarTypes.Localized);
return calw.GetWeekOfYear(DateTime.Parse("2012-01-01"), CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday).ToString();

これは 52 を返します。 (正解)

しかし、どうすれば年を取得できますか?

編集:

ここからの助けを借りて: http://codebetter.com/petervanooijen/2005/09/26/iso-weeknumbers-of-a-date-ac-implementation/

これはうまくいくようです:

 private int weekYear(DateTime fromDate)
    {
        GregorianCalendar cal = new GregorianCalendar(GregorianCalendarTypes.Localized);
        int week = weekNumber(fromDate);
        int month = cal.GetMonth(fromDate);
        int year = cal.GetYear(fromDate);

        //week starts after 31st december
        if (week > 50 && month == 1)
            year = year - 1;
        //week starts before 1st January
        if (week < 5 && month == 12)
            year = year + 1;

        return year;
    }
private int weekNumber(DateTime fromDate)
{
    // Get jan 1st of the year
    DateTime startOfYear = fromDate.AddDays(-fromDate.Day + 1).AddMonths(-fromDate.Month + 1);
    // Get dec 31st of the year
    DateTime endOfYear = startOfYear.AddYears(1).AddDays(-1);
    // ISO 8601 weeks start with Monday 
    // The first week of a year includes the first Thursday 
    // DayOfWeek returns 0 for sunday up to 6 for saterday
    int[] iso8601Correction = { 6, 7, 8, 9, 10, 4, 5 };
    int nds = fromDate.Subtract(startOfYear).Days + iso8601Correction[(int)startOfYear.DayOfWeek];
    int wk = nds / 7;
    switch (wk)
    {
        case 0:
            // Return weeknumber of dec 31st of the previous year
            return weekNumber(startOfYear.AddDays(-1));
        case 53:
            // If dec 31st falls before thursday it is week 01 of next year
            if (endOfYear.DayOfWeek < DayOfWeek.Thursday)
                return 1;
            else
                return wk;
        default: return wk;
    }
}
4

5 に答える 5

11

Noda Timeはこれを非常に簡単に処理します。

野田時間 v1.x

using System;
using NodaTime;

public class Test
{
    static void Main()
    {
        LocalDate date = new LocalDate(2012, 1, 1);
        Console.WriteLine($"WeekYear: {date.WeekYear}");             // 2011
        Console.WriteLine($"WeekOfWeekYear: {date.WeekOfWeekYear}"); // 52
    }
}

野田時間 v2.x

using System;
using NodaTime;
using NodaTime.Calendars;

public class Test
{
    static void Main()
    {
        LocalDate date = new LocalDate(2012, 1, 1);
        IWeekYearRule rule = WeekYearRules.Iso;
        Console.WriteLine($"WeekYear: {rule.GetWeekYear(date)}"); // 2011
        Console.WriteLine($"WeekOfWeekYear: {rule.GetWeekOfWeekYear(date)}"); // 52
    }
}

これは、週の年が最初の週に始まり、その年に少なくとも 4 日ある ISO カレンダー システムを使用しています。(のようにCalendarWeekRule.FirstFourDayWeek。) 別の暦体系が必要な場合は、LocalDateコンストラクターで指定します。1.x と 2.x では、週の年のルールの処理が少し異なります。

編集:これは、この状況(週年が暦年よりも小さい場合)と、週年が暦年よりも大きい場合がある年の反対側の状況の両方に正しい値を与えることに注意してください。たとえば、2012 年 12 月 31 日は 2013 年の週の 1 週目です。

これは、ライブラリにこれを実行してもらうことの利点です。ライブラリの仕事は、この種のことを理解することです。あなたのコードはそれについて心配する必要はありません。欲しいものだけ頼めるはずです。

于 2012-04-29T11:25:23.370 に答える
4

CalendarWeekRule次の方法で、週番号を取得できます。

var d = new DateTime(2012, 01, 01);
System.Globalization.CultureInfo cul = System.Globalization.CultureInfo.CurrentCulture;
var firstDayWeek = cul.Calendar.GetWeekOfYear(
    d,
    System.Globalization.CalendarWeekRule.FirstDay,
    DayOfWeek.Monday);
int weekNum = cul.Calendar.GetWeekOfYear(
    d,
    System.Globalization.CalendarWeekRule.FirstFourDayWeek,
    DayOfWeek.Monday);
int year = weekNum >= 52 && d.Month == 1 ? d.Year - 1 : d.Year;

CalendarWeekRule.FirstDayおそらく と比較したいと思うでしょうCalendarWeekRule.FirstFourDayWeek。このようにして、週番号と年を取得します (DateTime.Year-1それらが異なる場合)。

于 2012-04-29T10:57:54.693 に答える
2

これは、特別なコードを追加する必要がある単なるエッジ ケースです。日付文字列から年を取得し、週 = 52 で月 = 1 の場合、年から 1 を引きます。

于 2012-04-29T10:54:18.587 に答える