计算从4月开始的年份的周数

Wes*_*olf 1 c# datetime nodatime

我试图根据具体规则计算周数.我正在寻找的规则的例子是:

第1周= 4月1日集装箱的第一周.

示例数据:

2017年3月27日第1周2017年4月2日

...

2017年9月4日星期四2017年9月10日

我发现了一个类似的问题 - 从四月开始获得一周的周数 - 并以此为指导我已经提出了以下具体日期的工作.但是,在截止之前的日期时间,但在当前一周,会导致问题.

LocalDate firstOne = LocalDate.FromDateTime(dateTime);

int targetYear = firstOne.Month > 4 || firstOne.Month == 4 && firstOne.Day >= 1 ? firstOne.Year : firstOne.Year - 1;

LocalDate start = new LocalDate(targetYear, 4, 1);

int days = Period.Between(start, firstOne, PeriodUnits.Days).Days;
int targetWeek = (days / 7) + 1;

if (targetWeek >= 52)
{
    // if we are greater than 52 then we are technically in week 1 of the following year; eg 31st March 2017.
    // Remove the "year" from the week count and move the year counter back to the correct year.
    targetWeek -= 52;
    targetYear++;
}

return (targetYear, targetWeek);   
Run Code Online (Sandbox Code Playgroud)

目前的问题是,如果我在2017年3月27日通过,这是在第1天的7天内,它仍然给出了前一年和第52周.我猜我需要以某种方式考虑周开始日(?!).

Jon*_*eet 5

我如何处理这个问题取决于你需要做什么.在Noda Time 2.0(并向后移植到1.4)中IWeekYearRule,如果您想彻底完成此操作,可以实现一个界面.

如果你需要计算年份和周数,而不需要反方向,我会做这样的事情:

  • 找到与给定日历年对应的周年开始
  • 检查传入的日期是否在此之前或之后
    • 如果是,请使用该周开始年份进行计算
    • 否则,计算上一周 - 年的开始,并使用它

找到一周的开始非常简单DateAdjusters.PreviousOrSame,因为您可以说"这是星期一或4月1日之前"(根据需要调整星期几).

这是一个完整的示例,包含示例结果:

using System;
using NodaTime;

class Test
{
    static void Main()
    {
        ShowDate(2017, 1, 1);
        ShowDate(2017, 3, 27);
        ShowDate(2017, 9, 7);
    }

    private static void ShowDate(int year, int month, int day)
    {
        var date = new LocalDate(year, month, day);
        var result = GetWeekYearAndWeek(date);
        Console.WriteLine($"{date:uuuu-MM-dd} => {result}");
    }

    private static (int weekYear, int week) GetWeekYearAndWeek(LocalDate date)
    {
        // Initial guess...
        int weekYear = date.Year;
        var startOfWeekYear = GetStartOfWeekYear(weekYear);
        if (date < startOfWeekYear)
        {
            weekYear--;
            startOfWeekYear = GetStartOfWeekYear(weekYear);
        }

        int days = Period.Between(startOfWeekYear, date, PeriodUnits.Days).Days;
        int week = (days / 7) + 1;

        return (weekYear, week);
    }

    private const IsoDayOfWeek StartOfWeek = IsoDayOfWeek.Monday;

    private static LocalDate GetStartOfWeekYear(int weekYear) =>
        new LocalDate(weekYear, 4, 1).With(DateAdjusters.PreviousOrSame(StartOfWeek));
}
Run Code Online (Sandbox Code Playgroud)

输出:

2017-01-01 => (2016, 40)
2017-03-27 => (2017, 1)
2017-09-07 => (2017, 24)
Run Code Online (Sandbox Code Playgroud)