Skip to content

[migration/ilib-js-to-dart] feat(date): add julianday/rd options to ILibDateOptions and fix DateFmt calendar/timezone conversion - #95

Merged
gouniLee merged 10 commits into
migration/ilib-js-to-dartfrom
feat/dateoptions-julianday-rd
Jul 31, 2026
Merged

[migration/ilib-js-to-dart] feat(date): add julianday/rd options to ILibDateOptions and fix DateFmt calendar/timezone conversion#95
gouniLee merged 10 commits into
migration/ilib-js-to-dartfrom
feat/dateoptions-julianday-rd

Conversation

@gouniLee

@gouniLee gouniLee commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Checklist

The following lists affects Pub Points on pub.dev when the package is published.

  • Passed the all tests.
  • Verified that the example app works.
  • Executed the dart format command.
  • Added the API description is added if necessary.

Summary

Adds julianday / rd inputs to ILibDateOptions (parity with JS DateFactory) and fixes several calendar/timezone conversion bugs in ILibDateFmt.format() that were uncovered by a follow-up code review.

What changed

Feature

  • ILibDateOptions: new julianday and rd fields; _toCalendarDate() now cleanly separates the absolute-instant path (julianday/rd/unixtime/dateTime) from the component path.
  • toCalendarDate(): new public method exposing the resolved ILibCalendarDate (matches what JS DateFactory returns directly).
  • Locale-driven calendar: getCalendar() / _toCalendarDate() derive the calendar from locale when type/calendar is omitted, then fall back to gregorian.

Fixes

  • Absolute instant + type: DateFactory({unixtime, type:'islamic'})-style input no longer misreads the decomposed Gregorian components as being in the caller's calendar (was producing wildly wrong dates like October 19, 2585).
  • Timezone mismatch: format() now re-creates the date in the formatter's timezone when the input's timezone differs, gated on the date's timezone (matching JS (date.timezone || 'local') === formatterTz) rather than a formatter-explicit flag.
  • Local DateTime: a non-UTC DateTime (isUtc=false) is no longer double-offset during calendar conversion.
  • Caller components ignored for absolute instants: components are taken from the decomposed instant only, keeping them consistent with the hardcoded gregorian calendar.

Verification against iLib JS

All conversion results were checked 1:1 against iLib JS (DateFactory / DateFmt):

  • unixtime + type:islamic → gregorian formatter → July 4, 2024
  • unixtime → explicit islamic formatter → Ḏu al-Ḥijja 27, 1445 (= JS 1445-12-27) ✓
  • GregorianDate(tz:'Europe/Berlin') → en-US formatter → 6:00 AM (Berlin→NY) ✓

Notes

Two review findings were investigated and intentionally not changed, as current behavior already matches iLib JS:

  • ILibCalendarDate timezone comparison is unconditional (no formatter-explicit gate) — matches JS.
  • The B (flexible day-period) selection with midnight-wrapping periods matches JS output.

Motivation

Enables the JS two-step pattern in Dart:

// JS equivalent:
// var g = DateFactory({type:'gregorian', year, month, day, timezone:'local'});
// var d = DateFactory({julianday: g.getJulianDay(), locale: iLibLocale, timezone:'local'});

final ILibCalendarDate localDate = ILibDateOptions(
  julianday: ILibDateOptions(
    type: 'gregorian',
    year: gregorianYear, month: month, day: day,
    timezone: 'local',
  ).getJulianDay(),
  locale: iLibLocale,
  timezone: 'local',
).toCalendarDate();

Test plan

  • flutter test test/date/datefmt_datetime_calendar_extra_test.dart
  • flutter test test/date/datefmt_TimezoneCalendar_extra_test.dart
  • flutter test
  • Example app integration test (fa-IR / am-ET datetime formatting)

gouniLee added 2 commits July 30, 2026 16:15
…LibDateFmt

- Add julianday, rd fields to ILibDateOptions; _toCalendarDate() separates
  absolute-instant and component paths cleanly
- Derive calendar from locale when type/calendar is omitted
- Expose toCalendarDate() for locale-specific year/month/day access
- Fix _convertToFormatterCalendar: timezone mismatch triggers re-creation for
  ILibCalendarDate; timezone propagated through _createCalendarDate
- Fix local DateTime regression: utcConverted flag prevents double offset
  application when isUtc=false
- Add tests covering julianday/rd formatting, calendar conversion, locale-driven
  calendar selection, and the two-step gregorian → julianday → locale pattern
@gouniLee
gouniLee requested a review from seonmiJin July 30, 2026 07:35
@gouniLee gouniLee self-assigned this Jul 30, 2026
@seonmiJin

Copy link
Copy Markdown
Contributor

I've added test/date/datefmt_TimezoneCalendar_extra_test.dart.
Also, I've added these tests to the branch so they can be validated in JS iLib as well.
iLib-js/iLib@development...test-from-flutter-ilib

gouniLee added 3 commits July 31, 2026 13:03
_convertToFormatterCalendar gated timezone conversion on whether the
formatter's timezone was explicitly set (_explicitTimezone). This ignored
an ILibDateOptions' own timezone when the formatter timezone defaulted from
the locale, so a date with an explicit timezone formatted differently from
an equivalent ILibCalendarDate.

Gate on the date's own timezone instead (matches JS
(date.timezone || 'local') === formatterTz): convert only when the date
carries an explicit timezone differing from the formatter's. A null date
timezone means 'local' and needs no conversion, preserving the plain-
component and local-DateTime cases. Removes the _explicitTimezone field.
…tant

_resolveDateOptions merged the caller's year/month/day (via `?? dt.X`) with
the decomposed absolute instant. When an instant (dateTime/unixtime/
julianday/rd) was combined with explicit components in another calendar
(e.g. type:'islamic', year:1445), those components were kept but stamped
'gregorian', producing a wrong date.

Take all components from the decomposed dt only, so they stay consistent
with the hardcoded 'gregorian' calendar. No effect on normal usage, where
an absolute instant is passed alone.
@gouniLee gouniLee changed the title [migration/ilib-js-to-dart] feat(date): add julianday/rd options and fix calendar conversion in ILibDateFmt [migration/ilib-js-to-dart] feat(date): add julianday/rd options to ILibDateOptions and fix DateFmt calendar/timezone conversion Jul 31, 2026
@gouniLee

Copy link
Copy Markdown
Contributor Author

I've added test/date/datefmt_TimezoneCalendar_extra_test.dart. Also, I've added these tests to the branch so they can be validated in JS iLib as well. iLib-js/iLib@development...test-from-flutter-ilib

I’ve made updates so that everything works, including the test files you added, and I also updated the code after validating more diverse edge cases. Please check them again.

@gouniLee
gouniLee merged commit eb93c6d into migration/ilib-js-to-dart Jul 31, 2026
1 check passed
@gouniLee
gouniLee deleted the feat/dateoptions-julianday-rd branch July 31, 2026 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants