blob: c3874b540308db82d8563c1b2d6a19c25a1fa449 [file] [edit]
/// A tool to create the .tzf databases from a zoneinfo directory.
///
/// Usage example:
///
/// ```sh
/// dart run tool/encode_tzf --zoneinfo path/to/zoneinfo
/// ```
library;
import 'dart:io';
import 'package:args/args.dart';
import 'package:file/file.dart' as pkg_file;
import 'package:glob/glob.dart';
import 'package:glob/list_local_fs.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:timezone/src/common_locations.dart' show commonLocations;
import 'package:timezone/src/tools.dart';
import 'package:timezone/src/tzdb.dart';
import 'package:timezone/timezone.dart';
import 'package:timezone/tzdata.dart' as tzfile;
Future<void> main(List<String> arguments) async {
// Initialize logger
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
final log = Logger('main');
// Parse CLI arguments
final parser = ArgParser()
..addOption('output-all', defaultsTo: 'lib/data/latest_all.tzf')
..addOption('output-common', defaultsTo: 'lib/data/latest.tzf')
..addOption('output-10y', defaultsTo: 'lib/data/latest_10y.tzf')
..addOption('zoneinfo');
final args = parser.parse(arguments);
final zoneinfoPath = args['zoneinfo'] as String?;
if (zoneinfoPath == null) {
print('Usage:\n${parser.usage}');
exit(1);
}
final db = LocationDatabase();
log.info('Importing zoneinfo files');
final files = await Glob('**').list(root: zoneinfoPath).toList();
for (final f in files) {
if (f is pkg_file.File) {
final name = p.relative(f.path, from: zoneinfoPath).replaceAll('\\', '/');
log.info('- $name:$f');
db.add(
tzfileLocationToNativeLocation(
tzfile.Location.fromBytes(name, await f.readAsBytes()),
),
);
}
}
void logReport(FilterReport r) {
log.info(
' + locations: ${r.originalLocationsCount} => '
'${r.newLocationsCount}',
);
log.info(
' + transitions: ${r.originalTransitionsCount} => '
'${r.newTransitionsCount}',
);
}
log.info('Building location databases:');
log.info('- all locations');
final allDb = filterTimeZoneData(db);
logReport(allDb.report);
log.info('- common locations from all locations');
final commonDb = filterTimeZoneData(allDb.db, locations: commonLocations);
logReport(commonDb.report);
log.info('- [+- 5 years] from common locations');
final common10yDb = filterTimeZoneData(
commonDb.db,
dateFrom: DateTime(DateTime.now().year - 5, 1, 1).millisecondsSinceEpoch,
dateTo: DateTime(DateTime.now().year + 5, 1, 1).millisecondsSinceEpoch,
locations: commonLocations,
);
logReport(common10yDb.report);
log.info('Serializing location databases');
Future<void> write(String file, LocationDatabase db) =>
File(file).writeAsBytes(tzdbSerialize(db), flush: true);
await write(args['output-all'] as String, allDb.db);
await write(args['output-common'] as String, commonDb.db);
await write(args['output-10y'] as String, common10yDb.db);
}