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

时间:2017-09-07 08:38:39

标签: c# datetime nodatime

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

  

第1周= 4月1日容器的第一周。

示例数据:

  

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

     

...

     

2017年9月23日第23周2017年9月10日

我发现了一个类似的问题 - Getting Week number of year starting from April - 并以此作为指导我已经提出了以下内容,这些内容将来的具体日期有效。但是,在截止之前的日期时间,但是在当前一周,会导致问题。

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

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

1 个答案:

答案 0 :(得分: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));
}

输出:

2017-01-01 => (2016, 40)
2017-03-27 => (2017, 1)
2017-09-07 => (2017, 24)