-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ECMA402 datetime format to package:intl4x (#680)
* Adding Datetime format * Add tests * Rename Datetime -> DateTime * Add readme check * Add changelog entry * Fix tests * Revert name change * Switch to stable health workflow * Allow number in package names * Add checkmark * Fix merge problems * Rev pubspec * Add platforms to pubspec * Renaming options * Fixes * Export Options from all formatters * fix readme example
- Loading branch information
Showing
22 changed files
with
678 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 0.5.0 | ||
|
||
- Add `DateTime` formatting. | ||
|
||
## 0.4.0 | ||
|
||
- Add a `Locale` class. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ | |
|
||
export 'src/collation/collation.dart'; | ||
export 'src/collation/collation_options.dart'; | ||
export 'src/options.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
export 'src/datetime_format/datetime_format.dart'; | ||
export 'src/datetime_format/datetime_format_options.dart'; | ||
export 'src/options.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import '../test_checker.dart'; | ||
import 'datetime_format_impl.dart'; | ||
import 'datetime_format_options.dart'; | ||
|
||
/// `DateTime` formatting, for example: | ||
/// | ||
/// ```dart | ||
/// final date = DateTime.utc(2021, 12, 17, 4, 0, 42); | ||
/// Intl(locale: const Locale(language: 'fr')) | ||
/// .datetimeFormat(const DateTimeFormatOptions( | ||
/// hour: TimeRepresentation.numeric, | ||
/// hourCycle: HourCycle.h12, | ||
/// dayPeriod: DayPeriod.narrow, | ||
/// timeZone: 'UTC', | ||
/// )) | ||
/// .format(date); // Output: '4 mat.' | ||
/// ``` | ||
class DateTimeFormat { | ||
final DateTimeFormatOptions _options; | ||
final DateTimeFormatImpl impl; | ||
|
||
DateTimeFormat(this._options, this.impl); | ||
|
||
String format(DateTime datetime) { | ||
if (isInTest) { | ||
return '$datetime//${impl.locale}'; | ||
} else { | ||
return impl.formatImpl(datetime, _options); | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
pkgs/intl4x/lib/src/datetime_format/datetime_format_4x.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import '../locale.dart'; | ||
import 'datetime_format_impl.dart'; | ||
import 'datetime_format_options.dart'; | ||
|
||
DateTimeFormatImpl getDateTimeFormatter4X(Locale locale) => | ||
DateTimeFormat4X(locale); | ||
|
||
class DateTimeFormat4X extends DateTimeFormatImpl { | ||
DateTimeFormat4X(super.locale); | ||
|
||
@override | ||
String formatImpl(DateTime datetime, DateTimeFormatOptions options) { | ||
throw UnimplementedError('Insert diplomat bindings here'); | ||
} | ||
} |
160 changes: 160 additions & 0 deletions
160
pkgs/intl4x/lib/src/datetime_format/datetime_format_ecma.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import 'package:js/js.dart'; | ||
import 'package:js/js_util.dart'; | ||
|
||
import '../locale.dart'; | ||
import '../options.dart'; | ||
import 'datetime_format_impl.dart'; | ||
import 'datetime_format_options.dart'; | ||
|
||
DateTimeFormatImpl? getDateTimeFormatterECMA( | ||
Locale locale, | ||
LocaleMatcher localeMatcher, | ||
) => | ||
_DateTimeFormatECMA.tryToBuild(locale, localeMatcher); | ||
|
||
@JS('Intl.DateTimeFormat') | ||
class _DateTimeFormatJS { | ||
external factory _DateTimeFormatJS([List<String> locale, Object options]); | ||
external String format(Object num); | ||
} | ||
|
||
@JS('Intl.DateTimeFormat.supportedLocalesOf') | ||
external List<String> _supportedLocalesOfJS( | ||
List<String> listOfLocales, [ | ||
Object options, | ||
]); | ||
|
||
@JS('Date') | ||
class DateJS { | ||
external factory DateJS( | ||
int year, | ||
int monthIndex, | ||
int day, | ||
int hours, | ||
int minutes, | ||
int seconds, | ||
int milliseconds, | ||
); | ||
|
||
external factory DateJS.fromTimeStamp(int timeStamp); | ||
} | ||
|
||
@JS('Date.UTC') | ||
// ignore: non_constant_identifier_names | ||
external int UTC( | ||
int year, | ||
int monthIndex, | ||
int day, | ||
int hours, | ||
int minutes, | ||
int seconds, | ||
int milliseconds, | ||
); | ||
|
||
class _DateTimeFormatECMA extends DateTimeFormatImpl { | ||
_DateTimeFormatECMA(super.locale); | ||
|
||
static DateTimeFormatImpl? tryToBuild( | ||
Locale locale, | ||
LocaleMatcher localeMatcher, | ||
) { | ||
final supportedLocales = supportedLocalesOf(localeMatcher, locale); | ||
return supportedLocales.isNotEmpty | ||
? _DateTimeFormatECMA(supportedLocales.first) | ||
: null; //TODO: Add support to force return an instance instead of null. | ||
} | ||
|
||
static List<Locale> supportedLocalesOf( | ||
LocaleMatcher localeMatcher, | ||
Locale locale, | ||
) { | ||
final o = newObject<Object>(); | ||
setProperty(o, 'localeMatcher', localeMatcher.jsName); | ||
return List.from(_supportedLocalesOfJS([locale.toLanguageTag()], o)) | ||
.whereType<String>() | ||
.map(Locale.parse) | ||
.toList(); | ||
} | ||
|
||
@override | ||
String formatImpl(DateTime datetime, DateTimeFormatOptions options) { | ||
final datetimeFormatJS = _DateTimeFormatJS( | ||
[locale.toLanguageTag()], | ||
options.toJsOptions(), | ||
); | ||
return datetimeFormatJS.format(datetime.toJs()); | ||
} | ||
} | ||
|
||
extension on DateTime { | ||
DateJS toJs() { | ||
if (isUtc) { | ||
return DateJS.fromTimeStamp( | ||
UTC(year, month - 1, day, hour, minute, second, millisecond)); | ||
} else { | ||
return DateJS(year, month - 1, day, hour, minute, second, millisecond); | ||
} | ||
} | ||
} | ||
|
||
extension on DateTimeFormatOptions { | ||
Object toJsOptions() { | ||
final o = newObject<Object>(); | ||
setProperty(o, 'localeMatcher', localeMatcher.jsName); | ||
if (dateFormatStyle != null) { | ||
setProperty(o, 'dateStyle', dateFormatStyle!.name); | ||
} | ||
if (timeFormatStyle != null) { | ||
setProperty(o, 'timeStyle', timeFormatStyle!.name); | ||
} | ||
if (calendar != null) setProperty(o, 'calendar', calendar!.jsName); | ||
if (dayPeriod != null) setProperty(o, 'dayPeriod', dayPeriod!.name); | ||
if (numberingSystem != null) { | ||
setProperty(o, 'numberingSystem', numberingSystem!.name); | ||
} | ||
if (timeZone != null) setProperty(o, 'timeZone', timeZone!); | ||
if (clockstyle != null) { | ||
setProperty(o, 'hour12', clockstyle!.is12Hour); | ||
if (clockstyle!.startAtZero != null) { | ||
setProperty(o, 'hourCycle', clockstyle!.hourStyleJsString()); | ||
} | ||
} | ||
if (weekday != null) setProperty(o, 'weekday', weekday!.name); | ||
if (era != null) setProperty(o, 'era', era!.name); | ||
if (year != null) setProperty(o, 'year', year!.jsName); | ||
if (month != null) setProperty(o, 'month', month!.jsName); | ||
if (day != null) setProperty(o, 'day', day!.jsName); | ||
if (hour != null) setProperty(o, 'hour', hour!.jsName); | ||
if (minute != null) setProperty(o, 'minute', minute!.jsName); | ||
if (second != null) setProperty(o, 'second', second!.jsName); | ||
if (fractionalSecondDigits != null) { | ||
setProperty(o, 'fractionalSecondDigits', fractionalSecondDigits!); | ||
} | ||
if (timeZoneName != null) { | ||
setProperty(o, 'timeZoneName', timeZoneName!.name); | ||
} | ||
setProperty(o, 'formatMatcher', formatMatcher.jsName); | ||
return o; | ||
} | ||
} | ||
|
||
extension on ClockStyle { | ||
String hourStyleJsString() { | ||
// The four possible values are h11, h12, h23, h24. | ||
final firstDigit = is12Hour ? 1 : 2; | ||
|
||
final subtrahend = startAtZero! ? 1 : 0; | ||
final secondDigit = firstDigit * 2 - subtrahend; | ||
|
||
/// The cases are | ||
/// * firstDigit == 1 && subtrahend == 1 --> h11 | ||
/// * firstDigit == 1 && subtrahend == 0 --> h12 | ||
/// * firstDigit == 2 && subtrahend == 1 --> h23 | ||
/// * firstDigit == 2 && subtrahend == 0 --> h24 | ||
return 'h$firstDigit$secondDigit'; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
pkgs/intl4x/lib/src/datetime_format/datetime_format_impl.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import '../ecma/ecma_policy.dart'; | ||
import '../locale.dart'; | ||
import '../options.dart'; | ||
import '../utils.dart'; | ||
import 'datetime_format_4x.dart'; | ||
import 'datetime_format_options.dart'; | ||
import 'datetime_format_stub.dart' | ||
if (dart.library.js) 'datetime_format_ecma.dart'; | ||
|
||
/// This is an intermediate to defer to the actual implementations of | ||
/// datetime formatting. | ||
abstract class DateTimeFormatImpl { | ||
final Locale locale; | ||
|
||
DateTimeFormatImpl(this.locale); | ||
|
||
String formatImpl(DateTime datetime, DateTimeFormatOptions options); | ||
|
||
factory DateTimeFormatImpl.build( | ||
Locale locale, | ||
LocaleMatcher localeMatcher, | ||
EcmaPolicy ecmaPolicy, | ||
) => | ||
buildFormatter( | ||
locale, | ||
localeMatcher, | ||
ecmaPolicy, | ||
getDateTimeFormatterECMA, | ||
getDateTimeFormatter4X, | ||
); | ||
} |
Oops, something went wrong.