diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7fae870..4548020 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,8 +28,13 @@ jobs: - name: Analyze run: dart analyze lib + - name: Run Bucharest timezone regression + env: + TZ: Europe/Bucharest + run: dart test --tags bucharest_tz + - name: Run tests - run: dart test --coverage coverage + run: dart test --exclude-tags bucharest_tz --coverage coverage - name: Coverage run: dart run coverage:format_coverage -l -i ./coverage/test/time_test.dart.vm.json -o ./coverage/lcov.info diff --git a/dart_test.yaml b/dart_test.yaml new file mode 100644 index 0000000..c1212c7 --- /dev/null +++ b/dart_test.yaml @@ -0,0 +1,2 @@ +tags: + bucharest_tz: diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index bc7a7ef..f656bf8 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -139,8 +139,8 @@ extension DateTimeTimeExtension on DateTime { bool isAtSameMicrosecondAs(DateTime other) => isAtSameMillisecondAs(other) && microsecond == other.microsecond; static int _calculateDifference(DateTime date) { - final now = clock.now(); - return DateTime(date.year, date.month, date.day).difference(DateTime(now.year, now.month, now.day)).inDays; + final now = date.isUtc ? clock.now().toUtc() : clock.now(); + return date.date.difference(now.date).inDays; } /// Returns a range of dates to [to], exclusive start, inclusive end diff --git a/pubspec.yaml b/pubspec.yaml index 5a02585..6e1d5a7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,3 +17,4 @@ dev_dependencies: lints: ^6.0.0 test: ^1.28.0 coverage: ^1.15.0 + timezone: ^0.11.0 diff --git a/test/time_test.dart b/test/time_test.dart index 282d512..88ededb 100644 --- a/test/time_test.dart +++ b/test/time_test.dart @@ -1,9 +1,12 @@ import 'package:clock/clock.dart'; import 'package:test/test.dart'; import 'package:time/time.dart'; +import 'package:timezone/timezone.dart' as tz; +import 'package:timezone/data/latest.dart' as tz; void main() { final date = DateTime(2000, 1, 1); + tz.initializeTimeZones(); group('TimeExtension', () { group('Integers', () { @@ -126,6 +129,43 @@ void main() { expect(reconstructed, equals(original)); }); + test( + 'handles utc isToday correctly across DST switch', + () { + final location = tz.getLocation('Europe/Bucharest'); + tz.setLocalLocation(location); + final now = tz.TZDateTime.local(2026, 3, 29, 16); + + withClock(Clock.fixed(now), () { + final todayUtc = DateTime.utc(2026, 3, 29); + final tomorrowUtc = DateTime.utc(2026, 3, 30); + + // Older implementation of _calculateDifference from time: 2.1.6. + int oldCalculateDifference(DateTime date) { + final now = clock.now(); + return DateTime(date.year, date.month, date.day).difference( + DateTime(now.year, now.month, now.day), + ).inDays; + } + + expect( + oldCalculateDifference(todayUtc), + 0, + reason: 'Old implementation will mark UTC today as today.', + ); + expect( + oldCalculateDifference(tomorrowUtc), + 0, + reason: 'Old implementation will mark UTC tomorrow as today.', + ); + + expect(todayUtc.isToday, true, reason: 'New implementation handles UTC correctly.'); + expect(tomorrowUtc.isToday, false, reason: 'New implementation handles UTC correctly.'); + }); + }, + tags: ['bucharest_tz'], + ); + test('can handle isToday', () { final today = date; withClock(Clock.fixed(today), () {