mirror of
https://github.com/acamarata/hijri-core-dart.git
synced 2026-07-01 03:04:28 +00:00
Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2f947b011 | ||
|
|
eb1890b4ef | ||
|
|
c79368a4ee | ||
|
|
5dd4cecc12 |
5 changed files with 56 additions and 9 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -5,6 +5,16 @@ 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/).
|
||||
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
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -234,13 +234,12 @@ int _fcnaDaysInMonth(int hy, int hm) {
|
|||
// ---- FCNA Gregorian -> Hijri ----
|
||||
|
||||
HijriDate? _fcnaToHijri(DateTime date) {
|
||||
// FCNA criterion is UTC-based, so UTC date components ensure correct round-trips.
|
||||
// Normalize to UTC calendar day so the result is deterministic regardless of
|
||||
// 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 =
|
||||
DateTime.utc(
|
||||
date.year,
|
||||
date.month,
|
||||
date.day,
|
||||
).millisecondsSinceEpoch.toDouble();
|
||||
DateTime.utc(d.year, d.month, d.day).millisecondsSinceEpoch.toDouble();
|
||||
|
||||
final kApprox = _utcMsToKApprox(inputMs - 15 * msPerDay);
|
||||
final k0 = kApprox.floor();
|
||||
|
|
|
|||
|
|
@ -36,7 +36,11 @@ int _dateUtcMs(int year, int month, int day) {
|
|||
}
|
||||
|
||||
HijriDate? _uaqToHijri(DateTime date) {
|
||||
final inputUtc = _dateUtcMs(date.year, date.month, date.day);
|
||||
// Normalize to UTC calendar day so the result is deterministic regardless of
|
||||
// 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.
|
||||
int lo = 0;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ name: hijri_core
|
|||
description: >
|
||||
Hijri/Gregorian calendar conversion for Dart and Flutter. Pluggable engine
|
||||
system with built-in Umm al-Qura and FCNA calendars. Zero dependencies.
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
homepage: 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
|
||||
publisher: ariccamarata.com
|
||||
topics:
|
||||
- hijri
|
||||
- islamic
|
||||
|
|
|
|||
|
|
@ -93,6 +93,41 @@ 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 ----
|
||||
|
||||
group('UAQ isValid', () {
|
||||
|
|
|
|||
Loading…
Reference in a new issue