From 214e3f09734ed9026caba0f68c1527c4051094c7 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 18 Dec 2025 17:15:44 +0100 Subject: [PATCH 1/2] make offset a duration --- CHANGELOG.md | 4 ++++ lib/src/date_time.dart | 24 ++++++++++-------------- lib/src/location.dart | 28 +++++++++++++++++++--------- lib/src/tools.dart | 2 +- lib/src/tzdb.dart | 4 ++-- pubspec.yaml | 2 +- 6 files changed, 37 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ccf0b1..304c140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.11.0 + +- Make `Location.offset` a `Duration` instead of an `int`. + # 0.10.2 - Upgrade minimum SDK to `^3.10.0` and the databases to [2025c]. diff --git a/lib/src/date_time.dart b/lib/src/date_time.dart index d52db31..02aacef 100644 --- a/lib/src/date_time.dart +++ b/lib/src/date_time.dart @@ -22,12 +22,12 @@ class TZDateTime implements DateTime { // Get the offset at local (first estimate). final localInstant = local.millisecondsSinceEpoch; final localTimezone = location.lookupTimeZone(localInstant); - final localOffset = localTimezone.timeZone.offset; + final localOffset = localTimezone.timeZone.offset.inMilliseconds; // Adjust localInstant using the estimate and recalculate the offset. final adjustedInstant = localInstant - localOffset; final adjustedTimezone = location.lookupTimeZone(adjustedInstant); - final adjustedOffset = adjustedTimezone.timeZone.offset; + final adjustedOffset = adjustedTimezone.timeZone.offset.inMilliseconds; var milliseconds = localInstant - adjustedOffset; @@ -42,7 +42,8 @@ class TZDateTime implements DateTime { location .lookupTimeZone(localInstant - adjustedOffset) .timeZone - .offset) { + .offset + .inMilliseconds) { milliseconds = adjustedInstant; } } @@ -269,9 +270,7 @@ class TZDateTime implements DateTime { ); TZDateTime._(this.native, this.location, this.timeZone) - : _localDateTime = _isUtc(location) - ? native - : native.add(_timeZoneOffset(timeZone)); + : _localDateTime = _isUtc(location) ? native : native.add(timeZone.offset); /// Constructs a new [TZDateTime] instance based on [formattedString]. /// @@ -377,10 +376,10 @@ class TZDateTime implements DateTime { if (isUtc) { return '$y-$m-$d$sep$h:$min:$sec.$ms${us}Z'; } else { - final offSign = offset.sign >= 0 ? '+' : '-'; - offset = offset.abs() ~/ 1000; - final offH = _twoDigits(offset ~/ 3600); - final offM = _twoDigits((offset % 3600) ~/ 60); + final offSign = offset.isNegative ? '-' : '+'; + final offsetSeconds = offset.abs().inSeconds; + final offH = _twoDigits(offsetSeconds ~/ 3600); + final offM = _twoDigits((offsetSeconds % 3600) ~/ 60); return '$y-$m-$d$sep$h:$min:$sec.$ms$us$offSign$offH$offM'; } @@ -490,10 +489,7 @@ class TZDateTime implements DateTime { /// local time. Java, C# and Ruby return the difference between local time and /// UTC. @override - Duration get timeZoneOffset => _timeZoneOffset(timeZone); - - static Duration _timeZoneOffset(TimeZone timeZone) => - Duration(milliseconds: timeZone.offset); + Duration get timeZoneOffset => timeZone.offset; /// The year. @override diff --git a/lib/src/location.dart b/lib/src/location.dart index 3a52237..58f8899 100644 --- a/lib/src/location.dart +++ b/lib/src/location.dart @@ -71,7 +71,8 @@ class Location { /// translate instant in time expressed as milliseconds since /// January 1, 1970 00:00:00 UTC to this [Location]. int translate(int millisecondsSinceEpoch) { - return millisecondsSinceEpoch + timeZone(millisecondsSinceEpoch).offset; + return millisecondsSinceEpoch + + timeZone(millisecondsSinceEpoch).offset.inMilliseconds; } /// translate instant in time expressed as milliseconds since @@ -84,14 +85,18 @@ class Location { var utc = millisecondsSinceEpoch; - if (tz.offset != 0) { - utc -= tz.offset; + final offset = tz.offset.inMilliseconds; + if (offset != 0) { + utc -= offset; if (utc < start) { utc = - millisecondsSinceEpoch - lookupTimeZone(start - 1).timeZone.offset; + millisecondsSinceEpoch - + lookupTimeZone(start - 1).timeZone.offset.inMilliseconds; } else if (utc >= end) { - utc = millisecondsSinceEpoch - lookupTimeZone(end).timeZone.offset; + utc = + millisecondsSinceEpoch - + lookupTimeZone(end).timeZone.offset.inMilliseconds; } } @@ -151,8 +156,9 @@ class Location { final start = t.start; final end = t.end; - if (tz.offset != 0) { - final utc = millisecondsSinceEpoch - tz.offset; + final offset = tz.offset.inMilliseconds; + if (offset != 0) { + final utc = millisecondsSinceEpoch - offset; if (utc < start) { tz = lookupTimeZone(start - 1).timeZone; @@ -242,10 +248,14 @@ class Location { /// A [TimeZone] represents a single time zone such as CEST or CET. class TimeZone { // ignore: constant_identifier_names - static const TimeZone UTC = TimeZone(0, isDst: false, abbreviation: 'UTC'); + static const TimeZone UTC = TimeZone( + Duration.zero, + isDst: false, + abbreviation: 'UTC', + ); /// Milliseconds east of UTC. - final int offset; + final Duration offset; /// Is this [TimeZone] Daylight Savings Time? final bool isDst; diff --git a/lib/src/tools.dart b/lib/src/tools.dart index 9c231ca..4ebfd33 100644 --- a/lib/src/tools.dart +++ b/lib/src/tools.dart @@ -533,7 +533,7 @@ Location tzfileLocationToNativeLocation(tzfile.Location loc) { for (final z in loc.zones) { zones.add( TimeZone( - z.offset * 1000, + Duration(seconds: z.offset), isDst: z.isDst, abbreviation: loc.abbreviations[z.abbreviationIndex], ), diff --git a/lib/src/tzdb.dart b/lib/src/tzdb.dart index 510bf28..be7c717 100644 --- a/lib/src/tzdb.dart +++ b/lib/src/tzdb.dart @@ -122,7 +122,7 @@ Uint8List _serializeLocation(Location location) { offset = zonesOffset; for (var i = 0; i < location.zones.length; i++) { final zone = location.zones[i]; - buffer.setInt32(offset, zone.offset ~/ 1000); // convert to sec + buffer.setInt32(offset, zone.offset.inSeconds); // convert to sec buffer.setUint8(offset + 4, zone.isDst ? 1 : 0); buffer.setUint8(offset + 5, zoneAbbreviationOffsets[i]); offset += 8; @@ -203,7 +203,7 @@ Location _deserializeLocation(Uint8List data) { offset = zonesOffset; assert((offset % 4) == 0); for (var i = 0; i < zonesLength; i++) { - final zoneOffset = bdata.getInt32(offset) * 1000; // convert to ms + final zoneOffset = Duration(seconds: bdata.getInt32(offset)); final zoneIsDst = bdata.getUint8(offset + 4); final zoneAbbreviationIndex = bdata.getUint8(offset + 5); offset += 8; diff --git a/pubspec.yaml b/pubspec.yaml index e476e9f..ab2fecd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: timezone description: Time zone databases and time zone aware `DateTime`. repository: https://github.com/srawlins/timezone -version: 0.10.2 +version: 0.11.0 environment: sdk: ^3.10.0 From b27799489945e6daf3055750c13534e46281a346 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 23 Dec 2025 19:46:47 +0100 Subject: [PATCH 2/2] make final --- lib/src/date_time.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/date_time.dart b/lib/src/date_time.dart index 02aacef..9b13de4 100644 --- a/lib/src/date_time.dart +++ b/lib/src/date_time.dart @@ -361,7 +361,7 @@ class TZDateTime implements DateTime { String toIso8601String() => _toString(iso8601: true); String _toString({bool iso8601 = true}) { - var offset = timeZone.offset; + final offset = timeZone.offset; final y = _fourDigits(year); final m = _twoDigits(month);