inDaylightTime method

bool inDaylightTime(
  1. ILibDate date, {
  2. bool wallTime = false,
})

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;
}