X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f4370376b6e5a3df8b3f2cd1637483554af2fa4a..fe7cefd493837b49e8095b87aad1a01679eb7592:/src/common/datetime.cpp diff --git a/src/common/datetime.cpp b/src/common/datetime.cpp index 05ceb27e0d..669d0a3269 100644 --- a/src/common/datetime.cpp +++ b/src/common/datetime.cpp @@ -5,7 +5,6 @@ // Author: Vadim Zeitlin // Modified by: // Created: 11.05.99 -// RCS-ID: $Id$ // Copyright: (c) 1999 Vadim Zeitlin // parts of code taken from sndcal library by Scott E. Lee: // @@ -1130,10 +1129,37 @@ wxDateTime& wxDateTime::Set(const struct tm& tm) return *this; } - else - { - return Set(timet); + + // mktime() only adjusts tm_wday, tm_yday and tm_isdst fields normally, if + // it changed anything else, it must have performed the DST adjustment. But + // the trouble with this is that different implementations do it + // differently, e.g. GNU libc moves the time forward if the specified time + // is invalid in the local time zone, while MSVC CRT moves it backwards + // which is especially pernicious as it can change the date if the DST + // starts at midnight, as it does in some time zones (see #15419), and this + // is completely unexpected for the code working with dates only. + // + // So standardize on moving the time forwards to have consistent behaviour + // under all platforms and to avoid the problem above. + if ( tm2.tm_hour != tm.tm_hour ) + { + tm2 = tm; + tm2.tm_hour++; + if ( tm2.tm_hour == 24 ) + { + // This shouldn't normally happen as the DST never starts at 23:00 + // but if it does, we have a problem as we need to adjust the day + // as well. However we stop here, i.e. we don't adjust the month + // (or the year) because mktime() is supposed to take care of this + // for us. + tm2.tm_hour = 0; + tm2.tm_mday++; + } + + timet = mktime(&tm2); } + + return Set(timet); } wxDateTime& wxDateTime::Set(wxDateTime_t hour, @@ -1921,7 +1947,6 @@ wxDateTime::GetWeekOfYear(wxDateTime::WeekFlags flags, const TimeZone& tz) const { // adjust the weekdays to non-US style. wdYearStart = ConvertWeekDayToMondayBase(wdYearStart); - wdTarget = ConvertWeekDayToMondayBase(wdTarget); // quoting from http://www.cl.cam.ac.uk/~mgk25/iso-time.html: // @@ -1937,22 +1962,24 @@ wxDateTime::GetWeekOfYear(wxDateTime::WeekFlags flags, const TimeZone& tz) const // // if Jan 1 is Thursday or less, it is in the first week of this year - if ( wdYearStart < 4 ) - { - // count the number of entire weeks between Jan 1 and this date - week = (nDayInYear + wdYearStart + 6 - wdTarget)/7; + int dayCountFix = wdYearStart < 4 ? 6 : -1; + + // count the number of week + week = (nDayInYear + wdYearStart + dayCountFix) / DAYS_PER_WEEK; - // be careful to check for overflow in the next year - if ( week == 53 && tm.mday - wdTarget > 28 ) - week = 1; + // check if we happen to be at the last week of previous year: + if ( week == 0 ) + { + week = wxDateTime(31, Dec, GetYear() - 1).GetWeekOfYear(); } - else // Jan 1 is in the last week of the previous year + else if ( week == 53 ) { - // check if we happen to be at the last week of previous year: - if ( tm.mon == Jan && tm.mday < 8 - wdYearStart ) - week = wxDateTime(31, Dec, GetYear()-1).GetWeekOfYear(); - else - week = (nDayInYear + wdYearStart - 1 - wdTarget)/7; + int wdYearEnd = (wdYearStart + 364 + IsLeapYear(GetYear())) + % DAYS_PER_WEEK; + + // Week 53 only if last day of year is Thursday or later. + if ( wdYearEnd < 3 ) + week = 1; } }