c# - How to do I invert the week returned from Calendar.GetWeekOfYear back to a DateTime? -
this question has answer here:
- calculate date week number 23 answers
the problem there not seem built-in way datetime calculated "week number".
what want have work times , cultural calendars.
datetime dt1 = new datetime.now; int week = cal.getweekofyear(dt); datetime dt2 = getdatetimefromyearandweek(dt.year, week); if (dt1 < dt2 || dt2 > dt2.adddays(7.0)) { throw new exception("new datetime limits not span existing datetime; }
i think 1 of issues cultures, cal.getweekofyear(dt)
call return correct week number different year dt.year. means can't use in call fictious getdatetimefromyearandweek
call.
my own answer three-fold. first, came wrapper calendar.getweekofyear
returns "year" of week, since year may not same year of datetime
object.
public static void getweek(datetime dt, cultureinfo ci, out int week, out int year) { year = dt.year; week = ci.calendar.getweekofyear(dt, ci.datetimeformat.calendarweekrule, ci.datetimeformat.firstdayofweek); int prevweek = ci.calendar.getweekofyear(dt.adddays(-7.0), ci.datetimeformat.calendarweekrule, ci.datetimeformat.firstdayofweek); if (prevweek + 1 == week) { // year of prevweek should correct year = dt.adddays(-7.0).year; } else { // stay here year = dt.year; } }
next, here meat of answer. inverts year
, weekofyear
datetime
object. note used middle of year, because seems avoid problems singularities of new year (where 52 or 53 may or not wrap around 1). synchronize date finding date indeed first day of week, avoiding problems negative offsets comparing 2 dayofweek values.
public static datetime firstdateofweek(int year, int weekofyear, cultureinfo ci) { datetime jul1 = new datetime(year, 7, 1); while (jul1.dayofweek != ci.datetimeformat.firstdayofweek) { jul1 = jul1.adddays(1.0); } int refweek = ci.calendar.getweekofyear(jul1, ci.datetimeformat.calendarweekrule, ci.datetimeformat.firstdayofweek); int weekoffset = weekofyear - refweek; return jul1.adddays(7 * weekoffset ); }
and doubt it, here unit test cycles through lots of dates , cultures make sure works on of them.
public static void testdates() { foreach (cultureinfo ci in cultureinfo.getcultures(culturetypes.allcultures).where((x)=>!x.isneutralculture && x.calendar.algorithmtype == calendaralgorithmtype.solarcalendar)) { (int year = 2010; year < 2040; year++) { // first try bunch of hours in year // convert date -> week -> date (int hour = 0; hour < 356 * 24; hour+= 6) { datetime dt = new datetime(year, 1, 1).addhours(hour); int ww; int wyear; gener8.serialnumber.getweek(dt, ci, out ww, out wyear); if (wyear != year) { //console.writeline("{0} warning: {1} {2} {3}", ci.name, dt, year, wyear); } datetime dt1 = gener8.serialnumber.firstdateofweek(wyear, ww, ci); datetime dt2 = gener8.serialnumber.firstdateofweek(wyear, ww, ci).adddays(7.0); if (dt < dt1 || dt > dt2) { console.writeline("{3} bad date {0} not between {1} , {2}", dt, dt1, dt2, ci.name); } } // next try bunch of weeks in year // convert week -> date -> week (int week = 1; week < 54; week++) { datetime dt0 = firstdateofweek(year, week, ci); int ww0; int wyear0; getweek(dt0, ci, out ww0, out wyear0); datetime dt1 = dt0.adddays(6.9); int ww1; int wyear1; getweek(dt1, ci, out ww1, out wyear1); if ((dt0.year == year && ww0 != week) || (dt1.year == year && ww1 != week)) { console.writeline("{4} bad date {0} ww0={1} ww1={2}, week={3}", dt0, ww0, ww1, week, ci.name); } } } } }
Comments
Post a Comment