inDaylightTime method
Whether daylight-saving time is in effect for date in this zone.
Set wallTime true when date carries local wall-clock components rather
than an absolute UTC instant.
Implementation
bool inDaylightTime(ILibDate date, {bool wallTime = false}) {
if (_isLocal) {
// System time zone: probe the OS for the offset at this instant and compare it
// to the daylight (max) offset. The dst flag disambiguates the DST-end
// overlap, where the same wall time occurs twice.
if (_offsetJan1 == _offsetJun1) {
return false;
}
double offMs = _offset * 60000;
if (date.dst == false) {
offMs += _dstSavings * 60000;
}
final double daylight =
_offsetJan1 > _offsetJun1 ? _offsetJan1 : _offsetJun1;
return sysOffsetMinutesForInstant(_instantMillis(date) - offMs.round()) ==
daylight;
}
if (_zone == null) {
return false;
}
if (!_useDaylightTime()) {
return false;
}
// The Gregorian RD of the date's instant, regardless of its calendar.
// getJulianDay() is the absolute Julian Day, so subtracting the Gregorian epoch
// yields the Gregorian RD in the same time base the rules are evaluated against.
final double rd = date.getJulianDay() - GregRataDie.epoch;
final int year = GregRataDie.calcYear(rd);
final Map<String, dynamic> startRule = _zone!['s'] as Map<String, dynamic>;
final Map<String, dynamic> endRule = _zone!['e'] as Map<String, dynamic>;
// These calculate the start/end in local wall time.
double startRd = _calcRuleStart(startRule, year);
double endRd = _calcRuleStart(endRule, year);
if (wallTime) {
// rd is local wall time: skip the missing hour at the start of DST when
// standard time ends and daylight time begins.
startRd += _dstSavings / 1440;
} else {
// rd is a UTC instant: convert the boundaries to UTC so they can be compared
// directly. When DST starts the time is standard already, so subtract the
// offset; when DST ends it is daylight already, so subtract the DST savings
// then the offset.
startRd -= _offset / 1440;
endRd -= (_offset + _dstSavings) / 1440;
}
// Magic overlap hour at the end of DST: the same local wall time occurs twice.
// When the date carries an explicit dst flag and falls in that window, trust it.
final bool? dst = date.dst;
if (dst != null && rd < endRd && endRd - rd <= _dstSavings / 1440) {
return dst;
}
// Half-ms tolerance absorbs the sub-nanosecond JD round-trip error
// (rd + epoch - epoch ≠ rd in IEEE 754) without affecting 1-ms boundaries.
const double halfMs = 0.5 / 86400000.0;
final double rdC = rd + halfMs;
if (startRd < endRd) {
return rdC >= startRd && rdC < endRd;
}
return rdC >= startRd || rdC < endRd;
}