从C#中的年份,周数,日期名称中检索日期

时间:2016-03-09 08:09:07

标签: c#

通过提供年份,周数和日期名称,从C#中检索日期已经成为一个大问题。

假设我有

Year = 2016
Week number = 1
Day Name ='FRI'
First day of week='SUN'

预期结果:

01-01-2016

我该怎么做?

2 个答案:

答案 0 :(得分:1)

有许多周编号方案。例如,ISO-8601计算整周,因此2016-01-01是2015年第53周。您的预期结果表明您希望从1/1开始计数,而不是从第一整周开始计算。

您可以使用像NodaTime这样的库already supports计算年,周数和日期的日期来避免麻烦:

LocalDate date = LocalDate.FromWeekYearWeekAndDay(year, week, IsoDayOfWeek.Monday);

如果您不想使用外部图书馆,那么"技巧"是查找第一周的开始日期,向其添加指定的周数,然后添加与目标工作日相对应的天数:

var year=2016;
var weekNumber=1;
var dayOfWeek=(int)DayOfWeek.Friday;

//Doesn't really matter when the week starts
var firstDayOfWeek=(int)DayOfWeek.Sunday;

var yearStart=new DateTime(year,1,1);
var firstWeekDate=yearStart.AddDays( firstDayOfWeek -(int)yearStart.DayOfWeek);
//Use Calendar to add the number of weeks
Calendar myCal = CultureInfo.InvariantCulture.Calendar;
var targetDate=myCal.AddWeeks(firstWeekDate,weekNumber-1)
                .AddDays(dayOfWeek - firstDayOfWeek);

结果是2016-1-1。对于第11周,结果将是2016-3-11

简化firstWeekDate代码变为:

var targetDate=myCal.AddWeeks(yearStart,weekNumber-1)
                    .AddDays(dayOfWeek - (int)yearStart.DayOfWeek);

作为一个看似如下的函数:

DateTime FromWeekYearWeekAndDay(int year, int weekNumber, DayOfWeek dayOfWeek,
                                CultureInfo cultureInfo=null)
{
    cultureInfo=cultureInfo??CultureInfo.InvariantCulture;
    Calendar myCal = cultureInfo.Calendar;

    var yearStart=new DateTime(year,1,1);
    var targetDate=myCal.AddWeeks(yearStart,weekNumber-1)
                    .AddDays((int)dayOfWeek - (int)yearStart.DayOfWeek);

     return targetDate;
}

最后一部分是解析日期名称。如果您使用完整的英文日名称,则可以使用Enum.Parse

var dayOfWeek=(int)Enum.Parse(typeof(DayOfWeek),"Friday");

对于缩写,您可以从CultureInfo的DateTimeFormat.AbbreviatedDayNames属性中检索日期缩写列表。缩写的索引位置对应于其DayOfWeek值。

为了使查找更容易,您可以将此列表转换为字典:

var abbreviations=CultureInfo.InvariantCulture.DateTimeFormat.AbbreviatedDayNames;
var dayDict=abbreviations.Select((name,idx)=>new{name,idx})
                         .ToDictionary(l=>l.name,
                                       l=>(DayOfWeek)l.idx,
                                       StringComparer.InvariantCultureIgnoreCase);
var dayOfWeek= dayDict["FRI"];

最后,您可以使用以下代码找到目标日期:

var dayOfWeek=dayDict["FRI"];
var targetDate=FromWeekYearWeekAndDay(2016,1,dayOfWeek);
//2016-01-01

var targetDate=FromWeekYearWeekAndDay(2016,11,dayOfWeek);
//2016-3-11

答案 1 :(得分:0)

好的,假设你想要在Y年的工作日X,在W周。

public static DateTime FirstDateOfWeekISO8601(int year, int weekOfYear)
{
    DateTime jan1 = new DateTime(year, 1, 1);
    int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;

    DateTime firstThursday = jan1.AddDays(daysOffset);
    var cal = CultureInfo.CurrentCulture.Calendar;
    int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

    var weekNum = weekOfYear;
    if (firstWeek <= 1)
    {
        weekNum -= 1;
    }
    var result = firstThursday.AddDays(weekNum * 7);
    return result.AddDays(-3);
}

现在你有了W周的第一天。 现在你使用

DateTime input = FirstDateOfWeekISO8601(y, w);
input.DayOfWeek

这可以让你在第0天获得星期几。 现在,您可以使用input.AddDays(1)循环,直到您有搜索的那一天。

for(int i = 0; i < 7; ++i)
{
    if(input.AddDays(i).DayOfWeek == "here you need to the number from X which you passs as a string")
}

或者你可以减去两天的周期值,但在这种情况下你需要正确处理负值,因为一周的第一天不必是星期一。