mirror of
https://github.com/acamarata/hijri-core-dart.git
synced 2026-07-02 19:50:40 +00:00
Compare commits
No commits in common. "main" and "v1.0.0" have entirely different histories.
5 changed files with 9 additions and 56 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -5,16 +5,6 @@ All notable changes to this project will be documented in this file.
|
||||||
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
This project adheres to [Semantic Versioning](https://semver.org/).
|
This project adheres to [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
## 1.0.1
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- `toHijri` now normalizes the input `DateTime` to its UTC calendar day before
|
|
||||||
lookup (via `date.toUtc()`), matching the UTC-midnight contract of `toGregorian`.
|
|
||||||
Previously, passing a local `DateTime` on a host west of UTC could return the
|
|
||||||
previous Hijri day, breaking `toHijri(toGregorian(y, m, d))` round-trips.
|
|
||||||
Applies to both the UAQ and FCNA engines.
|
|
||||||
|
|
||||||
## [1.0.0] - 2026-05-25
|
## [1.0.0] - 2026-05-25
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -234,12 +234,13 @@ int _fcnaDaysInMonth(int hy, int hm) {
|
||||||
// ---- FCNA Gregorian -> Hijri ----
|
// ---- FCNA Gregorian -> Hijri ----
|
||||||
|
|
||||||
HijriDate? _fcnaToHijri(DateTime date) {
|
HijriDate? _fcnaToHijri(DateTime date) {
|
||||||
// Normalize to UTC calendar day so the result is deterministic regardless of
|
// FCNA criterion is UTC-based, so UTC date components ensure correct round-trips.
|
||||||
// the host timezone and whether the caller passes a UTC or local DateTime.
|
|
||||||
// This is symmetric with toGregorian, which always returns DateTime.utc().
|
|
||||||
final d = date.toUtc();
|
|
||||||
final inputMs =
|
final inputMs =
|
||||||
DateTime.utc(d.year, d.month, d.day).millisecondsSinceEpoch.toDouble();
|
DateTime.utc(
|
||||||
|
date.year,
|
||||||
|
date.month,
|
||||||
|
date.day,
|
||||||
|
).millisecondsSinceEpoch.toDouble();
|
||||||
|
|
||||||
final kApprox = _utcMsToKApprox(inputMs - 15 * msPerDay);
|
final kApprox = _utcMsToKApprox(inputMs - 15 * msPerDay);
|
||||||
final k0 = kApprox.floor();
|
final k0 = kApprox.floor();
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,7 @@ int _dateUtcMs(int year, int month, int day) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HijriDate? _uaqToHijri(DateTime date) {
|
HijriDate? _uaqToHijri(DateTime date) {
|
||||||
// Normalize to UTC calendar day so the result is deterministic regardless of
|
final inputUtc = _dateUtcMs(date.year, date.month, date.day);
|
||||||
// the host timezone and whether the caller passes a UTC or local DateTime.
|
|
||||||
// This is symmetric with toGregorian, which always returns DateTime.utc().
|
|
||||||
final d = date.toUtc();
|
|
||||||
final inputUtc = _dateUtcMs(d.year, d.month, d.day);
|
|
||||||
|
|
||||||
// Binary search: find the last table entry whose Gregorian start date <= input.
|
// Binary search: find the last table entry whose Gregorian start date <= input.
|
||||||
int lo = 0;
|
int lo = 0;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ name: hijri_core
|
||||||
description: >
|
description: >
|
||||||
Hijri/Gregorian calendar conversion for Dart and Flutter. Pluggable engine
|
Hijri/Gregorian calendar conversion for Dart and Flutter. Pluggable engine
|
||||||
system with built-in Umm al-Qura and FCNA calendars. Zero dependencies.
|
system with built-in Umm al-Qura and FCNA calendars. Zero dependencies.
|
||||||
version: 1.0.1
|
version: 1.0.0
|
||||||
homepage: https://github.com/acamarata/hijri-core-dart
|
homepage: https://github.com/acamarata/hijri-core-dart
|
||||||
repository: https://github.com/acamarata/hijri-core-dart
|
repository: https://github.com/acamarata/hijri-core-dart
|
||||||
issue_tracker: https://github.com/acamarata/hijri-core-dart/issues
|
issue_tracker: https://github.com/acamarata/hijri-core-dart/issues
|
||||||
|
publisher: ariccamarata.com
|
||||||
topics:
|
topics:
|
||||||
- hijri
|
- hijri
|
||||||
- islamic
|
- islamic
|
||||||
|
|
|
||||||
|
|
@ -93,41 +93,6 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---- UAQ round-trips (UTC day boundary) ----
|
|
||||||
|
|
||||||
group('UAQ round-trips', () {
|
|
||||||
test('toHijri(toGregorian(1446,9,1)) == 1446/9/1', () {
|
|
||||||
final greg = toGregorian(1446, 9, 1);
|
|
||||||
expect(greg, isNotNull);
|
|
||||||
final h = toHijri(greg!);
|
|
||||||
expect(h, isNotNull);
|
|
||||||
expect(h!.hy, equals(1446));
|
|
||||||
expect(h.hm, equals(9));
|
|
||||||
expect(h.hd, equals(1));
|
|
||||||
});
|
|
||||||
test('local DateTime with same UTC day round-trips correctly', () {
|
|
||||||
// toGregorian returns DateTime.utc(); converting it to local must still
|
|
||||||
// produce the correct Hijri day (regression for UTC-west hosts).
|
|
||||||
final greg = toGregorian(1446, 9, 1);
|
|
||||||
expect(greg, isNotNull);
|
|
||||||
final localGreg = greg!.toLocal();
|
|
||||||
final h = toHijri(localGreg);
|
|
||||||
expect(h, isNotNull);
|
|
||||||
expect(h!.hy, equals(1446));
|
|
||||||
expect(h.hm, equals(9));
|
|
||||||
expect(h.hd, equals(1));
|
|
||||||
});
|
|
||||||
test('toHijri(toGregorian(1318,1,1)) == 1318/1/1 (table lower bound)', () {
|
|
||||||
final greg = toGregorian(1318, 1, 1);
|
|
||||||
expect(greg, isNotNull);
|
|
||||||
final h = toHijri(greg!);
|
|
||||||
expect(h, isNotNull);
|
|
||||||
expect(h!.hy, equals(1318));
|
|
||||||
expect(h.hm, equals(1));
|
|
||||||
expect(h.hd, equals(1));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ---- UAQ isValid ----
|
// ---- UAQ isValid ----
|
||||||
|
|
||||||
group('UAQ isValid', () {
|
group('UAQ isValid', () {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue