任何人都知道一个简单的方法来获取本周第一天的日期(欧洲的星期一)。我知道年份和周数?我打算用C#做这个。
答案 0 :(得分:218)
我对@HenkHolterman的解决方案有疑问,即使是@RobinAndersson的解决方案。
阅读ISO 8601标准很好地解决了这个问题。使用第一个星期四作为目标,而不是星期一。以下代码也适用于2009年第53周。
public static DateTime FirstDateOfWeekISO8601(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;
// Use first Thursday in January to get first week of the year as
// it will never be in Week 52/53
DateTime firstThursday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var weekNum = weekOfYear;
// As we're adding days to a date in Week 1,
// we need to subtract 1 in order to get the right date for week #1
if (firstWeek == 1)
{
weekNum -= 1;
}
// Using the first Thursday as starting week ensures that we are starting in the right year
// then we add number of weeks multiplied with days
var result = firstThursday.AddDays(weekNum * 7);
// Subtract 3 days from Thursday to get Monday, which is the first weekday in ISO8601
return result.AddDays(-3);
}
答案 1 :(得分:36)
我喜欢Henk Holterman提供的解决方案。但是为了更加独立于文化,你必须得到当前文化的一周的第一天(它并不总是星期一):
using System.Globalization;
static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek - (int)jan1.DayOfWeek;
DateTime firstMonday = jan1.AddDays(daysOffset);
int firstWeek = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(jan1, CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek);
if (firstWeek <= 1)
{
weekOfYear -= 1;
}
return firstMonday.AddDays(weekOfYear * 7);
}
答案 2 :(得分:9)
最简单的方法可能是查找一年中的第一个星期一,然后添加相关的周数。这是一些示例代码。顺便说一下,它假定从1开始的周数:
using System;
class Test
{
static void Main()
{
// Show the third Tuesday in 2009. Should be January 20th
Console.WriteLine(YearWeekDayToDateTime(2009, DayOfWeek.Tuesday, 3));
}
static DateTime YearWeekDayToDateTime(int year, DayOfWeek day, int week)
{
DateTime startOfYear = new DateTime (year, 1, 1);
// The +7 and %7 stuff is to avoid negative numbers etc.
int daysToFirstCorrectDay = (((int)day - (int)startOfYear.DayOfWeek) + 7) % 7;
return startOfYear.AddDays(7 * (week-1) + daysToFirstCorrectDay);
}
}
答案 3 :(得分:4)
您应该可以使用System.Globalization.ISOWeek
方法来计算此内容。
您可以找到源代码here。
答案 4 :(得分:3)
就个人而言,我会利用文化信息来获取一周的日子,并循环到文化的一周的第一天。我不确定我是否正确解释它,这是一个例子:
public DateTime GetFirstDayOfWeek(int year, int weekNumber)
{
return GetFirstDayOfWeek(year, weekNumber, Application.CurrentCulture);
}
public DateTime GetFirstDayOfWeek(int year, int weekNumber,
System.Globalization.CultureInfo culture)
{
System.Globalization.Calendar calendar = culture.Calendar;
DateTime firstOfYear = new DateTime(year, 1, 1, calendar);
DateTime targetDay = calendar.AddWeeks(firstOfYear, weekNumber);
DayOfWeek firstDayOfWeek = culture.DateTimeFormat.FirstDayOfWeek;
while (targetDay.DayOfWeek != firstDayOfWeek)
{
targetDay = targetDay.AddDays(-1);
}
return targetDay;
}
答案 5 :(得分:2)
根据ISO 8601:1988 在瑞典使用,一年中的第一周是新年内至少有四天的第一周。
因此,如果您的一周从星期一开始,那么任何一年的第一个星期四都在第一周内。 你可以从那里添加DateAdd或DateDiff。
答案 6 :(得分:2)
使用Fluent DateTime http://fluentdatetime.codeplex.com/
var year = 2009;
var firstDayOfYear = new DateTime(year, 1, 1);
var firstMonday = firstDayOfYear.Next(DayOfWeek.Monday);
var weeksDateTime = 12.Weeks().Since(firstMonday);
答案 7 :(得分:2)
免费Time Period Library for .NET包含ISO 8601符合班周:
// ----------------------------------------------------------------------
public static DateTime GetFirstDayOfWeek( int year, int weekOfYear )
{
return new Week( year, weekOfYear ).FirstDayStart;
} // GetFirstDayOfWeek
答案 8 :(得分:2)
我尝试了一些上面的代码,有些代码有小错误,当你尝试不同的年份,不同的开始几周,你会看到它们,我拿了Jon Skeet的代码,修复它,它的工作原理非常简单。
Public Function YearWeekDayToDateTime(ByVal year As Integer, ByVal weekDay As Integer, ByVal week As Integer) As DateTime
' weekDay, day you want
Dim startOfYear As New DateTime(year, 1, 1)
Dim startOfYearFixDay As Integer
If startOfYear.DayOfWeek <> DayOfWeek.Sunday Then
startOfYearFixDay = startOfYear.DayOfWeek
Else
startOfYearFixDay = 7
End If
Return startOfYear.AddDays((7 * (week)) - startOfYearFixDay + weekDay)
End Function
答案 9 :(得分:2)
这是一种与Google Analytics的周数兼容的方法,以及我们在英特尔内部使用的相同编号方案,我确信它也会在很多其他环境中使用。
// Google Analytics does not follow ISO standards for date.
// It numbers week 1 starting on Jan. 1, regardless what day of week it starts on.
// It treats Sunday as the first day of the week.
// The first and last weeks of a year are usually not complete weeks.
public static DateTime GetStartDateTimeFromWeekNumberInYear(int year, uint weekOfYear)
{
if (weekOfYear == 0 || weekOfYear > 54) throw new ArgumentException("Week number must be between 1 and 54! (Yes, 54... Year 2000 had Jan. 1 on a Saturday plus 53 Sundays.)");
// January 1 -- first week.
DateTime firstDayInWeek = new DateTime(year, 1, 1);
if (weekOfYear == 1) return firstDayInWeek;
// Get second week, starting on the following Sunday.
do
{
firstDayInWeek = firstDayInWeek.AddDays(1);
} while (firstDayInWeek.DayOfWeek != DayOfWeek.Sunday);
if (weekOfYear == 2) return firstDayInWeek;
// Now get the Sunday of whichever week we're looking for.
return firstDayInWeek.AddDays((weekOfYear - 2)*7);
}
答案 10 :(得分:2)
这个对我有用,它还具有期望将cultureinfo作为参数来测试具有不同文化的公式的优点。如果为空,则获取当前的文化信息...有效值如下:“it”,“en-us”,“fr”,...等等。 诀窍是减去一年中第一天的周数,可以是1表示第一天在第一周内。希望这会有所帮助。
Public Shared Function FirstDayOfWeek(ByVal year As Integer, ByVal weekNumber As Integer, ByVal culture As String) As Date
Dim cInfo As System.Globalization.CultureInfo
If culture = "" Then
cInfo = System.Globalization.CultureInfo.CurrentCulture
Else
cInfo = System.Globalization.CultureInfo.CreateSpecificCulture(culture)
End If
Dim calendar As System.Globalization.Calendar = cInfo.Calendar
Dim firstOfYear As DateTime = New DateTime(year, 1, 1, calendar)
Dim firstDayWeek As Integer = calendar.GetWeekOfYear(firstOfYear, cInfo.DateTimeFormat.CalendarWeekRule, cInfo.DateTimeFormat.FirstDayOfWeek)
weekNumber -= firstDayWeek
Dim targetDay As DateTime = calendar.AddWeeks(firstOfYear, weekNumber)
Dim fDayOfWeek As DayOfWeek = cInfo.DateTimeFormat.FirstDayOfWeek
While (targetDay.DayOfWeek <> fDayOfWeek)
targetDay = targetDay.AddDays(-1)
End While
Return targetDay
End Function
答案 11 :(得分:1)
假设周数从1开始
DateTime dt = new DateTime(YearNumber, 1, 1).AddDays((WeekNumber - 1) * 7 - (WeekNumber == 1 ? 0 : 1));
return dt.AddDays(-(int)dt.DayOfWeek);
这应该会给你任何一周的第一天。我没有做过很多测试,但看起来很有效。它比我在网上找到的其他大多数解决方案都要小,所以想分享。
答案 12 :(得分:1)
轻微改变了Mikael Svenson代码。我找到了第一个星期一的一周,并适当改变了周数。
DateTime GetFirstWeekDay(int year, int weekNum)
{
Calendar calendar = CultureInfo.CurrentCulture.Calendar;
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
DateTime firstMonday = jan1.AddDays(daysOffset);
int firstMondayWeekNum = calendar.GetWeekOfYear(firstMonday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
DateTime firstWeekDay = firstMonday.AddDays((weekNum-firstMondayWeekNum) * 7);
return firstWeekDay;
}
答案 13 :(得分:0)
我简化了Mikael Svensson提供的代码,这对于欧洲许多国家来说是正确的。
public static DateTime FirstDateOfWeekIso8601(int year, int week)
{
var firstThursdayOfYear = new DateTime(year, 1, 1);
while (firstThursdayOfYear.DayOfWeek != DayOfWeek.Thursday)
{
firstThursdayOfYear = firstThursdayOfYear.AddDays(1);
}
var startDateOfWeekOne = firstThursdayOfYear.AddDays(-(DayOfWeek.Thursday - DayOfWeek.Monday));
return startDateOfWeekOne.AddDays(7 * (week - 1));
}
答案 14 :(得分:0)
我使用了其中一种解决方案,但它给了我错误的结果,仅仅因为它将星期日视为一周的第一天。
我改变了:
var firstDay = new DateTime(DateTime.Now.Year, 1, 1).AddDays((weekNumber - 1) * 7);
var lastDay = firstDay.AddDays(6);
到:
var lastDay = new DateTime(DateTime.Now.Year, 1, 1).AddDays((weekNumber) * 7);
var firstDay = lastDay.AddDays(-6);
现在它正在成为一种魅力。
答案 15 :(得分:0)
我已经编写并测试了以下代码,并且对我来说非常好。如果有人遇到麻烦,请告诉我,我也发布了一个问题,以便得到最好的答案。有人可能觉得它很有用。
public static DateTime GetFirstDateOfWeekByWeekNumber(int year, int weekNumber)
{
var date = new DateTime(year, 01, 01);
var firstDayOfYear = date.DayOfWeek;
var result = date.AddDays(weekNumber * 7);
if (firstDayOfYear == DayOfWeek.Monday)
return result.Date;
if (firstDayOfYear == DayOfWeek.Tuesday)
return result.AddDays(-1).Date;
if (firstDayOfYear == DayOfWeek.Wednesday)
return result.AddDays(-2).Date;
if (firstDayOfYear == DayOfWeek.Thursday)
return result.AddDays(-3).Date;
if (firstDayOfYear == DayOfWeek.Friday)
return result.AddDays(-4).Date;
if (firstDayOfYear == DayOfWeek.Saturday)
return result.AddDays(-5).Date;
return result.AddDays(-6).Date;
}
答案 16 :(得分:0)
目前,没有正确处理ISO 8601week号码的C#类。即使您可以实例化文化,寻找最接近的文化并更正,我认为最好自己进行完整的计算:
$('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
if (e.target=='#chartcontainer1') {
$('#layeredcolumnchart').html('YOUR HTML/JAVASCRIPT/ETC HERE');
// If you need to load jQuery plugins like charts, you need to load
// it here each time you display the tab-content
// $('#layeyedcolumnchart .somediv').somePlugin();
}
})
答案 17 :(得分:0)
我发现的最大问题之一是从周转换为日期,然后从日期转换为周。
主要问题是当试图从属于上一年一周的日期中获取正确的周年时。幸运的是 System.Globalization.ISOWeek.GetYear
处理了这个问题。
这是我的解决方案:
public class WeekOfYear
{
public static (int Year, int Week) DateToWeekOfYear(DateTime date) =>
(ISOWeek.GetYear(date), ISOWeek.GetWeekOfYear(date));
public static bool ValidYearAndWeek(int year, int week) =>
year >= 1 && year <= 9999 && week >= 1 && week <= 53 // bounds of year/week
&& !(year <= 1 && week <= 1) && !(year >= 9999 && week >= 53); // bounds of DateTime
public int Year { get; }
public int Week { get; }
public virtual DateTime StartOfWeek { get; protected set; }
public virtual DateTime EndOfWeek { get; protected set; }
public virtual IEnumerable<DateTime> DaysInWeek =>
Enumerable.Range(1, 10).Select(i => StartOfWeek.AddDays(i));
public WeekOfYear(int year, int week)
{
if (!ValidYearAndWeek(year, week))
throw new ArgumentException($"DateTime can't represent {week} of year {year}.");
Year = year;
Week = week;
StartOfWeek = ISOWeek.ToDateTime(year, week, DayOfWeek.Monday);
EndOfWeek = ISOWeek.ToDateTime(year, week, DayOfWeek.Sunday).AddDays(1).AddTicks(-1);
}
public WeekOfYear((int Year, int Week) week) : this(week.Year, week.Week) { }
public WeekOfYear(DateTime date) : this(DateToWeekOfYear(date)) { }
}
第二大问题是美国偏好从星期日开始的几周。
我使用上面的子类 WeekOfYear
提出的解决方案,并管理构造函数中的偏移量(将周转换为日期)和 DateToWeekOfYear
(将日期转换为周)。< /p>
public class UsWeekOfYear : WeekOfYear
{
public static new (int Year, int Week) DateToWeekOfYear(DateTime date)
{
// if date is a sunday, return the next week
if (date.DayOfWeek == DayOfWeek.Sunday) date = date.AddDays(1);
return WeekOfYear.DateToWeekOfYear(date);
}
public UsWeekOfYear(int year, int week) : base(year, week)
{
StartOfWeek = ISOWeek.ToDateTime(year, week, DayOfWeek.Monday).AddDays(-1);
EndOfWeek = ISOWeek.ToDateTime(year, week, DayOfWeek.Sunday).AddTicks(-1);
}
public UsWeekOfYear((int Year, int Week) week) : this(week.Year, week.Week) { }
public UsWeekOfYear(DateTime date) : this(DateToWeekOfYear(date)) { }
}
这是一些测试代码:
public static void Main(string[] args)
{
Console.WriteLine("== Last Week / First Week");
Log(new WeekOfYear(2020, 53));
Log(new UsWeekOfYear(2020, 53));
Log(new WeekOfYear(2021, 1));
Log(new UsWeekOfYear(2021, 1));
Console.WriteLine("\n== Year Crossover (iso)");
var start = new DateTime(2020, 12, 26);
var i = 0;
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2020-12-26 - Sat
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2020-12-27 - Sun
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2020-12-28 - Mon
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2020-12-29 - Tue
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2020-12-30 - Wed
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2020-12-30 - Thu
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2021-01-01 - Fri
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2021-01-02 - Sat
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2021-01-03 - Sun
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2021-01-04 - Mon
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2021-01-05 - Tue
Log(start.AddDays(i), new WeekOfYear(start.AddDays(i++))); // 2021-01-06 - Wed
Console.WriteLine("\n== Year Crossover (us)");
i = 0;
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2020-12-26 - Sat
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2020-12-27 - Sun
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2020-12-28 - Mon
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2020-12-29 - Tue
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2020-12-30 - Wed
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2020-12-30 - Thu
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2021-01-01 - Fri
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2021-01-02 - Sat
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2021-01-03 - Sun
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2021-01-04 - Mon
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2021-01-05 - Tue
Log(start.AddDays(i), new UsWeekOfYear(start.AddDays(i++))); // 2021-01-06 - Wed
var x = new UsWeekOfYear(2020, 53) as WeekOfYear;
}
public static void Log(WeekOfYear week)
{
Console.WriteLine($"{week} - {week.StartOfWeek:yyyy-MM-dd} ({week.StartOfWeek:ddd}) - {week.EndOfWeek:yyyy-MM-dd} ({week.EndOfWeek:ddd})");
}
public static void Log(DateTime date, WeekOfYear week)
{
Console.WriteLine($"{date:yyyy-MM-dd (ddd)} - {week} - {week.StartOfWeek:yyyy-MM-dd (ddd)} - {week.EndOfWeek:yyyy-MM-dd (ddd)}");
}
答案 18 :(得分:0)
当我们想要计算给定年份,周数和星期几的日期时,这是我的解决方案。
int Year = 2014;
int Week = 48;
int DayOfWeek = 4;
DateTime FecIni = new DateTime(Year, 1, 1);
FecIni = FecIni.AddDays(7 * (Week - 1));
if ((int)FecIni.DayOfWeek > DayOfWeek)
{
while ((int)FecIni.DayOfWeek != DayOfWeek) FecIni = FecIni.AddDays(-1);
}
else
{
while ((int)FecIni.DayOfWeek != DayOfWeek) FecIni = FecIni.AddDays(1);
}
答案 19 :(得分:0)
我已经提出了所提出的解决方案的精炼版本,这是一个更简单的参数化firstDayOfWeek:
public static DateTime GetFirstDayOfWeek(int year, int week, DayOfWeek firstDayOfWeek)
{
return GetWeek1Day1(year, firstDayOfWeek).AddDays(7 * (week - 1));
}
public static DateTime GetWeek1Day1(int year, DayOfWeek firstDayOfWeek)
{
DateTime date = new DateTime(year, 1, 1);
// Move towards firstDayOfWeek
date = date.AddDays(firstDayOfWeek - date.DayOfWeek);
// Either 1 or 52 or 53
int weekOfYear = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFullWeek, firstDayOfWeek);
// Move forwards 1 week if week is 52 or 53
date = date.AddDays(7 * System.Math.Sign(weekOfYear - 1));
return date;
}
答案 20 :(得分:0)
建议的解决方案尚未完成 - 它仅适用于CalendarWeekRule.FirstFullWeek。其他类型的周规则不起作用。使用此测试用例可以看出这一点:
foreach (CalendarWeekRule rule in Enum.GetValues(typeof(CalendarWeekRule)))
{
for (int year = 1900; year < 2000; year++)
{
DateTime date = FirstDateOfWeek(year, 1, rule);
Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, rule, DayOfWeek.Monday) == 1);
Assert(CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date.AddDays(-1), rule, DayOfWeek.Monday) != 1);
}
}
答案 21 :(得分:0)
我通过覆盖改进了托马斯的解决方案:
public static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
return Timer.FirstDateOfWeekOfMonth(year, 1, weekOfYear);
}
public static DateTime FirstDateOfWeekOfMonth(int year, int month,
int weekOfYear)
{
DateTime dtFirstDayOfMonth = new DateTime(year, month, 1);
//I also commented out this part:
/*
if (firstWeek <= 1)
{
weekOfYear -= 1;
}
*/
否则日期提前一周..
谢谢托马斯,非常有帮助。
答案 22 :(得分:0)
要双向转换,请参阅此处:Wikipedia article on ISO week dates
答案 23 :(得分:0)
第1周被定义为从星期一开始并包含一年中第一个星期四的那一周。