Skip to content
This repository was archived by the owner on Dec 19, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/src/date_time.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ class TZDateTime implements DateTime {
} else {
var unix = _localDateTime.millisecondsSinceEpoch;
var tzData = _location.lookupTimeZone(unix);
if (tzData.i1.offset != 0) {
final utc = unix - tzData.i1.offset;
if (utc < tzData.i2) {
tzData = _location.lookupTimeZone(tzData.i2 - 1);
} else if (utc >= tzData.i3) {
tzData = _location.lookupTimeZone(tzData.i3);
if (tzData.timeZone.offset != 0) {
final utc = unix - tzData.timeZone.offset;
if (utc < tzData.start) {
tzData = _location.lookupTimeZone(tzData.start - 1);
} else if (utc >= tzData.end) {
tzData = _location.lookupTimeZone(tzData.end);
}
unix -= tzData.i1.offset;
unix -= tzData.timeZone.offset;
}
_millisecondsSinceEpoch = unix;

Expand Down
45 changes: 26 additions & 19 deletions lib/src/location.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
/// and ported to Dart.
library timezone.src.location;

import 'package:tuple/tuple.dart';

/// Zone Info header size.
const int _zoneInfoHeaderSize = 16;

Expand Down Expand Up @@ -83,19 +81,19 @@ class Location {
/// January 1, 1970 00:00:00 to UTC.
int translateToUtc(int millisecondsSinceEpoch) {
final t = lookupTimeZone(millisecondsSinceEpoch);
final tz = t.i1;
final start = t.i2;
final end = t.i3;
final tz = t.timeZone;
final start = t.start;
final end = t.end;

var utc = millisecondsSinceEpoch;

if (tz.offset != 0) {
utc -= tz.offset;

if (utc < start) {
utc = millisecondsSinceEpoch - lookupTimeZone(start - 1).i1.offset;
utc = millisecondsSinceEpoch - lookupTimeZone(start - 1).timeZone.offset;
} else if (utc >= end) {
utc = millisecondsSinceEpoch - lookupTimeZone(end).i1.offset;
utc = millisecondsSinceEpoch - lookupTimeZone(end).timeZone.offset;
}
}

Expand All @@ -104,22 +102,22 @@ class Location {

/// lookup for [TimeZone] and its boundaries for an instant in time expressed
/// as milliseconds since January 1, 1970 00:00:00 UTC.
PersistentTuple3<TimeZone, int, int> lookupTimeZone(int millisecondsSinceEpoch) {
TzInstant lookupTimeZone(int millisecondsSinceEpoch) {
if (zones.isEmpty) {
return const PersistentTuple3(const TimeZone(0, false, 'UTC'), minTime, maxTime);
return const TzInstant(const TimeZone(0, false, 'UTC'), minTime, maxTime);
}

if (_cacheZone != null &&
millisecondsSinceEpoch >= _cacheStart &&
millisecondsSinceEpoch < _cacheEnd) {
return new PersistentTuple3(_cacheZone, _cacheStart, _cacheEnd);
return new TzInstant(_cacheZone, _cacheStart, _cacheEnd);
}

if (transitionAt.isEmpty || millisecondsSinceEpoch < transitionAt[0]) {
final zone = _firstZone();
final start = minTime;
final end = transitionAt.isEmpty ? maxTime : transitionAt.first;
return new PersistentTuple3(zone, start, end);
return new TzInstant(zone, start, end);
}

// Binary search for entry with largest millisecondsSinceEpoch <= sec.
Expand All @@ -139,30 +137,30 @@ class Location {
}
}

return new PersistentTuple3(zones[transitionZone[lo]], transitionAt[lo], end);
return new TzInstant(zones[transitionZone[lo]], transitionAt[lo], end);
}

/// timeZone method returns [TimeZone] in use at an instant in time expressed
/// as milliseconds since January 1, 1970 00:00:00 UTC.
TimeZone timeZone(int millisecondsSinceEpoch) {
return lookupTimeZone(millisecondsSinceEpoch).i1;
return lookupTimeZone(millisecondsSinceEpoch).timeZone;
}

/// timeZoneFromLocal method returns [TimeZone] in use at an instant in time
/// expressed as milliseconds since January 1, 1970 00:00:00.
TimeZone timeZoneFromLocal(int millisecondsSinceEpoch) {
final t = lookupTimeZone(millisecondsSinceEpoch);
var tz = t.i1;
final start = t.i2;
final end = t.i3;
var tz = t.timeZone;
final start = t.start;
final end = t.end;

if (tz.offset != 0) {
final utc = millisecondsSinceEpoch - tz.offset;

if (utc < start) {
tz = lookupTimeZone(start - 1).i1;
tz = lookupTimeZone(start - 1).timeZone;
} else if (utc >= end) {
tz = lookupTimeZone(end).i1;
tz = lookupTimeZone(end).timeZone;
}
}

Expand Down Expand Up @@ -255,4 +253,13 @@ class TimeZone {
}

String toString() => '[$abbr offset=$offset dst=$isDst]';
}
}

/// A [TzInstant] represents a timezone and an instant in time.
class TzInstant {
final TimeZone timeZone;
final int start;
final int end;

const TzInstant(this.timeZone, this.start, this.end);
}
12 changes: 9 additions & 3 deletions lib/src/tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
library timezone.src.tools;

import 'dart:collection';
import 'package:tuple/tuple.dart';
import 'package:timezone/tzdata.dart' as tzfile;
import 'package:timezone/timezone.dart';

Expand Down Expand Up @@ -1035,7 +1034,14 @@ class FilterReport {
int newTransitionsCount = 0;
}

Tuple2<LocationDatabase, FilterReport> filterTimeZoneData(
class FilteredLocationDatabase {
final LocationDatabase db;
final FilterReport report;

FilteredLocationDatabase(this.db, this.report);
}

FilteredLocationDatabase filterTimeZoneData(
LocationDatabase db,
{int dateFrom: TZDateTime.minMillisecondsSinceEpoch,
int dateTo: TZDateTime.maxMillisecondsSinceEpoch,
Expand Down Expand Up @@ -1093,7 +1099,7 @@ Tuple2<LocationDatabase, FilterReport> filterTimeZoneData(
report.newLocationsCount++;
}

return new Tuple2(result, report);
return new FilteredLocationDatabase(result, report);
}

/// Convert [tzfile.Location] to [Location]
Expand Down
3 changes: 1 addition & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ homepage: https://github.com/localvoid/timezone
environment:
sdk: '>=1.9.0'
dependencies:
tuple: '>=0.1.0 <0.2.0'
path: '>=1.3.0 <1.4.0'
path: '^1.3.0'
dev_dependencies:
args: any
browser: any
Expand Down
16 changes: 8 additions & 8 deletions tool/get.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,26 +145,26 @@ Future main(List<String> arguments) async {

log.info('- all locations');
final allDb = filterTimeZoneData(db, locations: allLocations);
logReport(allDb.i2);
logReport(allDb.report);

log.info('- common locations from all locations');
final commonDb = filterTimeZoneData(allDb.i1, locations: commonLocations);
logReport(commonDb.i2);
final commonDb = filterTimeZoneData(allDb.db, locations: commonLocations);
logReport(commonDb.report);

log.info('- [2010 - 2020 years] from common locations');
final common_2010_2020_Db = filterTimeZoneData(commonDb.i1,
final common_2010_2020_Db = filterTimeZoneData(commonDb.db,
dateFrom: new DateTime.utc(2010, 1, 1).millisecondsSinceEpoch,
dateTo: new DateTime.utc(2020, 1, 1).millisecondsSinceEpoch,
locations: commonLocations);
logReport(common_2010_2020_Db.i2);
logReport(common_2010_2020_Db.report);

log.info('Serializing location databases');
final allOut = new File(ospath.join(outPath, '${source}_all.$tzDataExtension'));
final commonOut = new File(ospath.join(outPath, '${source}.$tzDataExtension'));
final common_2010_2020_Out = new File(ospath.join(outPath, '${source}_2010-2020.$tzDataExtension'));
await allOut.writeAsBytes(tzdbSerialize(allDb.i1), flush: true);
await commonOut.writeAsBytes(tzdbSerialize(commonDb.i1), flush: true);
await common_2010_2020_Out.writeAsBytes(tzdbSerialize(common_2010_2020_Db.i1), flush: true);
await allOut.writeAsBytes(tzdbSerialize(allDb.db), flush: true);
await commonOut.writeAsBytes(tzdbSerialize(commonDb.db), flush: true);
await common_2010_2020_Out.writeAsBytes(tzdbSerialize(common_2010_2020_Db.db), flush: true);

exit(0);
}