Add a hack to work around DST problems in unit tests in BST
wxDateTime is still broken with respect to DST outside of the standard time_t range, but make a special exception for the dates near Unix epoch when using BST as not accounting for DST for them broke the unit tests when run in this time zone. Note that constructing the dates outside of the standard range is broken too, so if this problem is ever fully fixed in GetTm(), it would need to be fixed in Set() too, where the DST is not taken into account neither. The problems in unit tests were due to using the (correctly behaving) standard mktime() for 1970-01-01 but then using our (broken) GetTm() for accessing them and could, in principle, be also worked around by not using mktime() for this date, but it seems better to keep correct behaviour at least for it, even if it's still broken for many earlier dates. See #15370.
This commit is contained in:
@@ -341,6 +341,33 @@ void wxInitTm(struct tm& tm)
|
||||
tm.tm_isdst = -1; // auto determine
|
||||
}
|
||||
|
||||
// Internal helper function called only for times outside of standard time_t
|
||||
// range.
|
||||
//
|
||||
// It is just a hack to work around the fact that we can't call IsDST() and
|
||||
// related methods from GetTm() for the reasons explained there.
|
||||
static int GetDSTOffset(wxLongLong t)
|
||||
{
|
||||
bool isDST = false;
|
||||
|
||||
switch ( wxDateTime::GetCountry() )
|
||||
{
|
||||
case wxDateTime::UK:
|
||||
// We don't need to check for the end value in 1971 as this is
|
||||
// inside the standard range, so check just for beginning of the
|
||||
// permanent BST period in UK, see IsDST().
|
||||
if ( t < 0 &&
|
||||
t >= wxDateTime(27, wxDateTime::Oct, 1968).GetValue() )
|
||||
isDST = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return isDST ? wxDateTime::DST_OFFSET : 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// implementation of wxDateTime
|
||||
// ============================================================================
|
||||
@@ -1475,11 +1502,21 @@ wxDateTime::Tm wxDateTime::GetTm(const TimeZone& tz) const
|
||||
//else: use generic code below
|
||||
}
|
||||
|
||||
long secDiff = tz.GetOffset();
|
||||
|
||||
// We need to account for DST as always when converting to broken down time
|
||||
// components, but we can't call IsDST() from here because this would
|
||||
// result in infinite recursion as IsDST() starts by calling GetYear()
|
||||
// which just calls back to this function. So call a special function which
|
||||
// is used just here to determine the DST offset to add.
|
||||
if ( tz.IsLocal() )
|
||||
secDiff += GetDSTOffset(m_time);
|
||||
|
||||
wxLongLong timeMidnight = m_time + secDiff * 1000;
|
||||
|
||||
// remember the time and do the calculations with the date only - this
|
||||
// eliminates rounding errors of the floating point arithmetics
|
||||
|
||||
wxLongLong timeMidnight = m_time + tz.GetOffset() * 1000;
|
||||
|
||||
long timeOnly = (timeMidnight % MILLISECONDS_PER_DAY).ToLong();
|
||||
|
||||
// we want to always have positive time and timeMidnight to be really
|
||||
|
Reference in New Issue
Block a user