누구나 주중 첫날 (유럽의 월요일)을 쉽게 얻을 수있는 방법을 알고 있습니다. 연도와 주 번호를 알고 있습니까? 나는 C #에서 이것을 할 것입니다.
누구나 주중 첫날 (유럽의 월요일)을 쉽게 얻을 수있는 방법을 알고 있습니다. 연도와 주 번호를 알고 있습니까? 나는 C #에서 이것을 할 것입니다.
답변:
@RobinAndersson의 수정으로도 @HenkHolterman의 솔루션에 문제가있었습니다.
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);
}
나는 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);
}
firstMonday
월요일이 아닐 수도있는 잘못된 변수 이름입니다. =)
가장 쉬운 방법은 해당 연도의 첫 번째 월요일을 찾은 다음 관련 주 수를 추가하는 것입니다. 샘플 코드는 다음과 같습니다. 그것은 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);
}
}
개인적으로 나는 문화 정보를 이용하여 요일을 얻고 문화의 첫 요일로 넘어갑니다. 올바르게 설명하고 있는지 잘 모르겠습니다. 예를 들어 보겠습니다.
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;
}
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);
주 번호가 1에서 시작한다고 가정
DateTime dt = new DateTime(YearNumber, 1, 1).AddDays((WeekNumber - 1) * 7 - (WeekNumber == 1 ? 0 : 1));
return dt.AddDays(-(int)dt.DayOfWeek);
이것은 매주 첫날을 알려줄 것입니다. 나는 그것에 대해 많은 테스트를하지 않았지만 작동하는 것처럼 보입니다. 웹에서 찾은 대부분의 다른 솔루션보다 작은 솔루션이므로 공유하고 싶었습니다.
new DateTime(1,1,YearNumber)
이것은 나를 위해 일했으며 다른 culture로 수식을 테스트하기 위해 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
다음은 Google 웹 로그 분석의 주 번호와 호환되며 인텔에서 내부적으로 사용한 것과 동일한 번호 체계이며 다른 많은 상황에서도 사용됩니다.
// 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);
}
위의 코드 중 일부를 시도했지만 약간의 실수가 있습니다. 다른 시작 요일로 다른 해를 시도하면 코드를 볼 수 있습니다 .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
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;
}
1 주차는 월요일에 시작하여 연중 첫 번째 목요일을 포함하는 주로 정의됩니다.
양방향으로 변환하려면 여기를 참조하십시오 : ISO 주 날짜에 관한 Wikipedia 기사
재정의로 Thomas의 솔루션을 약간 개선했습니다.
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;
}
*/
그렇지 않으면 날짜가 일주일 전이었습니다.
토마스 감사합니다.
나는 해결책 중 하나를 사용했지만 일요일을 요일의 첫 번째 날로 간주하기 때문에 잘못된 결과를 얻었습니다.
나는 바꿨다 :
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);
그리고 지금 그것은 매력으로 일하고 있습니다.
제안 된 솔루션은 완전하지 않습니다-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);
}
}
나는 제안 된 솔루션의 정제 된 버전을 만들었고 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;
}
이것은 우리가 주어진 연도, 주 번호 및 요일을 계산할 때 내 솔루션입니다.
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);
}
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));
}
다음 코드를 작성하고 테스트했으며 완벽하게 작동합니다. 누구 든지이 문제에 직면하면 알려주십시오. 나는 최선의 답변을 얻기 위해 질문을 게시했습니다. 누군가 유용하다고 생각할 수도 있습니다.
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;
}
GetFirstDateOfWeekByWeekNumber(2020, 29)
2020 년 29 주 동안이 결과가 반환 07/20/2020
됩니다. 그러나 29 주째 첫날은07/13/2020
현재 ISO 8601 주 번호를 올바르게 처리하는 C # 클래스는 없습니다. 문화를 인스턴스화 할 수는 있지만 가장 가까운 것을 찾아서 수정하십시오. 나는 직접 계산을하는 것이 좋습니다.
/// <summary>
/// Converts a date to a week number.
/// ISO 8601 week 1 is the week that contains the first Thursday that year.
/// </summary>
public static int ToIso8601Weeknumber(this DateTime date)
{
var thursday = date.AddDays(3 - date.DayOfWeek.DayOffset());
return (thursday.DayOfYear - 1) / 7 + 1;
}
/// <summary>
/// Converts a week number to a date.
/// Note: Week 1 of a year may start in the previous year.
/// ISO 8601 week 1 is the week that contains the first Thursday that year, so
/// if December 28 is a Monday, December 31 is a Thursday,
/// and week 1 starts January 4.
/// If December 28 is a later day in the week, week 1 starts earlier.
/// If December 28 is a Sunday, it is in the same week as Thursday January 1.
/// </summary>
public static DateTime FromIso8601Weeknumber(int weekNumber, int? year = null, DayOfWeek day = DayOfWeek.Monday)
{
var dec28 = new DateTime((year ?? DateTime.Today.Year) - 1, 12, 28);
var monday = dec28.AddDays(7 * weekNumber - dec28.DayOfWeek.DayOffset());
return monday.AddDays(day.DayOffset());
}
/// <summary>
/// Iso8601 weeks start on Monday. This returns 0 for Monday.
/// </summary>
private static int DayOffset(this DayOfWeek weekDay)
{
return ((int)weekDay + 6) % 7;
}