Skip to content

Repository files navigation

General DateTime

Gregorian, Persian (Jalali), and Hijri (Umm al-Qura) chronology for Dart and Flutter. Convert exact instants, work with calendar fields and all-day dates, serialize values safely, and use Persian or Hijri calendars in Material date pickers.

pub.dev Calendar CI

Contents

Choose a package

Package Role Requires Flutter
general_datetime Chronology core re-exports and Material calendar/localization delegates Yes
general_datetime_core Calendar date-times, strict calendar systems, civil dates, and JSON storage No
general_date_format Localized Persian/Hijri formatting and multilingual Material adapters, in the neighboring repository Yes
general_date_format_core Localized Persian/Hijri formatting and parsing for servers and CLIs No

The Flutter wrapper re-exports the core's exact classes. A PersianDateTime created through either import has the same runtime type; there are no competing copies of the chronology engine.

Use these public libraries:

import 'package:general_datetime/general_datetime.dart'; // Chronology core APIs.
// Flutter adapters use separate public libraries:
import 'package:general_datetime/delegates.dart';
import 'package:general_datetime/default_localizations.dart';

For pure Dart, replace those imports with:

import 'package:general_datetime_core/general_datetime_core.dart';

Installation and local setup

The current wrapper version is general_datetime 4.0.0, with general_datetime_core 1.0.0. The Flutter wrapper requires Dart >=3.4.0 <4.0.0 and Flutter >=3.32.0; the core requires only Dart >=3.4.0 <4.0.0.

Add the Flutter wrapper to your application:

dependencies:
  general_datetime: ^4.0.0

Run flutter pub get. For a pure Dart application, use general_datetime_core: ^1.0.0 and run dart pub get instead.

The picker example uses this checkout's 4.0.0 wrapper through a path dependency. The calendar demo uses the two published 1.0.0 cores directly. Neither requires local dependency overrides.

When combining this wrapper with general_date_format 3.0.0, check the formatter's chronology constraint: its current manifest still requires general_datetime ^3.0.0, which excludes 4.0.0. The wrapper constraint must be aligned before both new wrapper versions can resolve together.

Quick start

import 'package:general_datetime/general_datetime.dart';

void main() {
  final native = DateTime.utc(2024, 3, 20, 12, 34, 56, 789, 123);
  final persian = PersianDateTime.fromDateTime(native);
  final hijri = HijriDateTime.fromDateTime(native);

  print(persian.toIso8601String()); // 1403-01-01T12:34:56.789123Z
  print(hijri.toIso8601String()); // 1445-09-10T12:34:56.789123Z
  print(persian.toDateTime().toIso8601String());
  // 2024-03-20T12:34:56.789123Z

  print(persian.microsecondsSinceEpoch == native.microsecondsSinceEpoch); // true
  print(hijri.isAtSameMomentAs(persian)); // true
}

PersianDateTime and HijriDateTime extend DateTime and implement GeneralDateTimeInterface. Their year/month/day getters use their own calendar, while their epoch values and duration operations describe the same native instant. Native Gregorian DateTime remains the Gregorian date-time implementation.

Supported calendars and bounds

Calendar Calendar fields, inclusive Gregorian UTC civil-day bounds Policy
Gregorian Native Dart date bounds -271821-04-20 through 275760-09-13 Proleptic Gregorian
Persian SH -61-01-01 through 3177-12-29 0560-03-20 through 3799-03-19 Published Tehran leap data for SH 1206–1498; finite Borkowski calculation elsewhere
Umm al-Qura AH 1300-01-01 through 1600-12-30 1882-11-12 through 2174-11-25 Finite verified month table; no arithmetic fallback

Persian years include zero. Calculated Persian dates outside SH 1206–1498 are not a guarantee of official historical usage or future astronomical decisions. Umm al-Qura is one specific Hijri chronology; observational/religious calendars and other Islamic algorithms may produce different dates.

Both calendar date-time classes expose:

API Meaning
minimumYear, maximumYear Supported calculation/table year bounds
minimumOfficialYear, maximumOfficialYear Published-data coverage
minimumGregorianDate, maximumGregorianDate First/last supported Gregorian day, at UTC midnight
hasOfficialCalendarData Whether the instance's year has published data
isSupportedDateTime(native) Whether the input's Gregorian wall date is supported in its UTC/local mode
isValidDate(year, month, day) Strict calendar-field validity, without normalization
daysInMonth(year, month) Month length; invalid month/year throws RangeError

Range checks apply to the resulting calendar wall date. Converting UTC/local mode or adding a duration near an endpoint can throw RangeError if the new wall date falls outside that calendar's bounds.

Data sources, hashes, independent fixtures, and source decisions are documented in Persian validation and Umm al-Qura validation.

Construction, validation, and parsing

Both classes provide the same constructor family:

Constructor Behavior
PersianDateTime(year, [month, day, hour, minute, second, millisecond, microsecond]) Local calendar wall fields
PersianDateTime.utc(...) UTC calendar wall fields
PersianDateTime.fromDateTime(value) Same instant and UTC/local mode, with Persian fields
PersianDateTime.now() Current local instant
PersianDateTime.timestamp() Current UTC instant
fromSecondsSinceEpoch, fromMillisecondsSinceEpoch, fromMicrosecondsSinceEpoch Epoch constructors; named isUtc defaults to false
parse(text), tryParse(text) Calendar-specific ISO-like input

Replace PersianDateTime with HijriDateTime for the Hijri equivalents. Optional month/day default to 1; all optional clock fields default to 0. fromDateTime also accepts another supported calendar subclass and preserves its epoch rather than reinterpreting its exposed fields. GeneralDateTimeInterface.now<PersianDateTime>() and the Hijri equivalent provide generic local clocks for those two registered types; other type arguments throw TypeError.

Constructors normalize overflow and negative components in the selected calendar:

final nextYear = PersianDateTime.utc(1403, 13, 1); // 1404-01-01
final nextDay = HijriDateTime.utc(1445, 9, 10, 25); // 1445-09-11 01:00
final valid = PersianDateTime.isValidDate(1403, 13, 1); // false

Normalization uses exact arithmetic before narrowing to supported values. Extreme inputs cannot wrap into ordinary dates; unsupported results throw RangeError. Exact cancellation that produces a supported date remains valid. For strict construction, use CalendarSystems.forId(...).construct(...) or CalendarDate rather than a normalizing date-time constructor.

Calendar-specific ISO-like parsing

final value = PersianDateTime.parse('1403-01-01T12:34:56.789123Z');
final shifted = HijriDateTime.parse('1445-09-10T03:30:00+03:30');
// shifted is UTC, with clock time 00:00.
final invalid = HijriDateTime.tryParse('not a date'); // null

These parsers read the receiving class's calendar, use ASCII digits, normalize calendar/clock overflow, and truncate fractions beyond six digits. Z or a numeric offset produces UTC; an omitted zone produces local time. Offsets are applied before the final supported-range check. Invalid syntax/offsets and unsupported results throw FormatException; tryParse returns null for those failures. These are permissive constructors, not strict input validators. For localized patterns and strict user input, use general_date_format.

Instants, arithmetic, and timezones

final start = PersianDateTime.utc(1403, 1, 1, 12);
final later = start.add(const Duration(hours: 36));
print(later.difference(start).inHours); // 36
print(later.subtract(const Duration(hours: 36)) == start); // true
final local = start.toLocal();
final utcAgain = local.toUtc(); // Same instant as start.

add, subtract, difference, compareTo, isBefore, isAfter, and isAtSameMomentAs operate on instants. Equality/hash keys follow native DateTime behavior: calendar field equality is not required for the same instant and UTC/local representation. Use isAtSameMomentAs when comparing across UTC/local modes.

A Duration(days: 1) is 24 elapsed hours. It need not land at the same wall clock time across DST. Use civil-date arithmetic for all-day navigation.

toDateTime() returns a native Gregorian value preserving epoch microseconds and UTC/local mode. toUtc() and toLocal() preserve the instant and retain the calendar subclass. Local timezone names/offsets and DST behavior come from the operating system; date-time instances do not retain an IANA timezone ID. Do not assume a named-zone TZDateTime keeps its named-zone semantics when converted to these classes.

secondsSinceEpoch rounds down to the containing Unix second, directly from microseconds. For example, -1 microsecond returns -1 second; -1000001 returns -2 seconds. Millisecond/microsecond epoch getters retain native behavior. Use microseconds or CalendarInstant storage when fractions matter.

Useful instance fields include name, monthLength, yearLength, isLeapYear, dayOfYear, julianDay, and hasOfficialCalendarData. weekday always uses Dart's Monday=1 through Sunday=7 convention.

Safe field operations

Calendar date-times expose custom fields through the DateTime interface. Dart's DateTime.copyWith extension and Flutter's Gregorian DateUtils helpers can reconstruct the wrong calendar from those fields. Use the package's helpers when the variable is statically typed DateTime:

DateTime selected = PersianDateTime.utc(1403, 1, 1, 12, 30, 0, 123, 456);
final next = CalendarDateUtils.copyWith(selected, day: 2);
// PersianDateTime, 1403-01-02, with clock fields and UTC preserved.
final midnight = CalendarDateUtils.dateOnly(selected);
// PersianDateTime.utc(1403, 1, 1).
final native = CalendarDateUtils.toGregorian(selected);
// DateTime.utc(2024, 3, 20, 12, 30, 0, 123, 456).

copyWith accepts all date/clock fields and isUtc, retaining omitted fields. It uses the input calendar's normalization and range checks. The concrete classes' own copyWith is also safe when called through their concrete static type. Native Gregorian values remain native; unregistered calendar interfaces throw UnsupportedError for field operations.

Changing isUtc through copyWith reinterprets wall fields. To preserve the instant, call toUtc()/toLocal() instead. dateOnly preserves UTC/local mode and is still a date-time: local DST rules may normalize a nonexistent midnight. For timezone-free dates use CalendarDate; for picker normalization use the matching calendar delegate.

Civil dates, periods, ranges, and weeks

CalendarDate is an immutable, strictly validated calendar date without a clock or timezone. Its calendar identifiers are CalendarId.gregory, CalendarId.persian, and CalendarId.islamicUmalqura.

final date = CalendarDate(
  calendar: CalendarId.persian, year: 1403, month: 6, day: 31,
);
final tomorrow = date.addDays(1); // 1403-07-01
final clamped = date.addMonths(1); // 1403-07-30
final carried = date.addMonths(1, policy: CalendarOverflow.overflow);
// 1403-08-01
final gregorian = date.toCalendar(CalendarId.gregory);
final record = date.toRecord(); // CalendarDateRecord for JSON storage.

addMonths and addYears offer explicit missing-day policies:

Policy Result when the destination lacks the original day
CalendarOverflow.clamp (default) Last valid day in the destination month
CalendarOverflow.reject ArgumentError
CalendarOverflow.overflow Carry excess days into the following month

Clamping is not reversible. Repeated monthly recurrences should retain the original requested date instead of repeatedly adding to a clamped result. Operations outside supported bounds fail explicitly.

CalendarDate.fromDateTime(value) extracts the input's calendar wall date and discards its clock/mode. It does not perform a timezone conversion. fromRecord restores a stored civil date. gregorianDay is UTC midnight used as a civil-day coordinate, not an event timestamp; dayIndex, weekday, and hasPublishedData expose day position and calendar coverage.

Civil-date equality/hash keys include the calendar tag. compareTo, isSameCivilDay, and daysUntil compare civil-day positions, so differently tagged dates can compare as zero while remaining unequal.

final start = CalendarDate(
  calendar: CalendarId.gregory, year: 2021, month: 1, day: 1,
);
final range = CalendarDateRange(start, start.addDays(7));
print(range.dayCount); // 7
print(range.contains(start.addDays(7))); // false: the end is excluded.
print(CalendarDateRange.inclusiveDayCount(start, start.addDays(7))); // 8
print(const CalendarWeekRules().weekOfYear(start)); // (year: 2020, week: 53)

CalendarWeekRules(firstWeekday: ..., minimumDays: ...) supports explicit week starts and first-week thresholds from 1–7. Defaults match ISO rules for the Gregorian calendar; on Persian/Hijri dates the week-year follows that calendar. startOfWeek and calculations needing an adjacent year can fail at calendar bounds.

Calendar system API

Use CalendarSystems.gregorian, .persian, .ummAlQura, or CalendarSystems.forId(id) for strict operations without switching on classes:

final system = CalendarSystems.forId(CalendarId.persian);
final value = system.construct(1403, 1, 1, hour: 12); // UTC by default.
final day = system.toGregorianDay(1403, 1, 1); // 2024-03-20 UTC midnight.
final fields = system.fromGregorianDay(DateTime.utc(2024, 3, 20));
// (year: 1403, month: 1, day: 1)

The interface includes validity, month/year lengths, minimumDate, maximumDate, hasPublishedData(year), dataRevision, and calculationPolicy. construct validates fields instead of normalizing them and rejects local wall times that DST changes during construction. fromInstant(value, isUtc: ...) converts an exact instant with the requested mode (default UTC).

fromGregorianDay requires native Gregorian fields and ignores their clock; calendar subclasses must use fromInstant instead. The built-in registry is closed. Implementing CalendarSystem or GeneralDateTimeInterface does not register a new calendar for field helpers, formatting, or version-1 storage.

JSON storage

Choose the record that matches your domain:

Value Record Required fields Optional fields
Timed event CalendarInstant version: 1, kind: "instant", timestamp, calendar timeZone
All-day calendar date CalendarDateRecord version: 1, kind: "calendar-date", calendar, integer year, month, day None

Identifiers are gregory, persian, and islamic-umalqura, available through CalendarId.identifier. Other Islamic algorithms are not aliases for Umm al-Qura.

import 'dart:convert';
import 'package:general_datetime/general_datetime.dart';

void main() {
  final date = PersianDateTime.utc(1403, 1, 1, 12, 34, 56, 789, 123);
  final stored = jsonEncode(
    CalendarInstant.fromDateTime(date, timeZone: 'Asia/Tehran'),
  );
  final restored = CalendarInstant.fromJson(jsonDecode(stored));
  print(restored.instant.toIso8601String()); // 2024-03-20T12:34:56.789123Z

  final allDay = CalendarDateRecord(
    calendar: CalendarId.persian, year: 1403, month: 1, day: 1,
  );
  final restoredDay = CalendarDateRecord.fromJson(jsonDecode(jsonEncode(allDay)));
  print(CalendarDate.fromRecord(restoredDay)); // persian:1403-01-01
}

The timestamp is authoritative and always decoded as native Gregorian UTC. The preferred calendar is metadata; display conversion is explicit. Optional timeZone is a nonempty trimmed string retained as opaque metadata. It is not validated against a zone database and does not apply an offset. Input local/UTC mode is not persisted.

Timestamp syntax is YYYY-MM-DDTHH:mm:ss[.fraction]Z, with Gregorian years 0000–9999 and at most six fractional digits. Encoder output uses three or six fractional digits. Decoding rejects offsets, missing seconds, leap seconds, excess precision, invalid/overflowing fields, and annotations. All-day records store only strictly validated fields, including signed Persian years, within the chosen calendar's bounds. fromDateTime extracts wall fields without converting them.

Both decoders throw FormatException for missing/unknown keys, wrong types, unknown identifiers, unsupported versions, or invalid values. Direct invalid record construction throws ArgumentError; encoding unregistered calendars throws UnsupportedError. Optional timeZone must be omitted rather than provided as null.

Calendar-specific toString()/toIso8601String() output is not a generic Gregorian timestamp. toUtc() still returns a calendar subclass. For a timestamp-only API, use:

final timestamp = CalendarDateUtils.toGregorian(date).toUtc().toIso8601String();

Do not represent an all-day calendar date by an implicit midnight timestamp.

Flutter Material pickers

A picker needs both a calendar delegate (date arithmetic) and matching MaterialLocalizations (date labels and input parsing).

Calendar Arithmetic delegate Built-in English localization
Persian PersianCalendarDelegate DefaultPersianCalendarMaterialLocalizations.delegate
Umm al-Qura HijriCalendarDelegate DefaultHijriCalendarMaterialLocalizations.delegate

The built-in localizations support English (en) only and use the legacy dd/mm/yyyy compact input format with ASCII digits. For translated labels, locale-specific date order, RTL languages, and native digits, use the Material localizations from general_date_format.

Complete Persian picker example

import 'package:flutter/material.dart';
import 'package:general_datetime/general_datetime.dart';
import 'package:general_datetime/delegates.dart';
import 'package:general_datetime/default_localizations.dart';

void main() => runApp(MaterialApp(
  localizationsDelegates: const [
    DefaultPersianCalendarMaterialLocalizations.delegate,
  ],
  home: Scaffold(
    body: CalendarDatePicker(
      initialDate: PersianDateTime(1403, 1, 1),
      firstDate: PersianDateTime(1400),
      lastDate: PersianDateTime(1410, 12, 29),
      calendarDelegate: const PersianCalendarDelegate(),
      onDateChanged: (DateTime selected) {
        debugPrint(CalendarDate.fromDateTime(selected).toString());
      },
    ),
  ),
));

For Hijri, replace all calendar date values, the arithmetic delegate, and the localization delegate with the corresponding Hijri types.

Every date argument to these delegates must have the matching runtime type, including comparisons, range endpoints, and non-null parser results. Incompatible dates throw ArgumentError, even if they describe the same instant or have the same numeric fields. Explicitly convert external Gregorian instants with the calendar's fromDateTime factory first. Invalid compact text returns null; a parser returning another calendar is a configuration error.

The delegates use local calendar wall dates for picker normalization/navigation. Date labels, input help, and parsing are forwarded to the ambient localization. When an app uses several calendar types, keep its global localizations and scope each picker with Localizations.override; avoid installing competing Material delegates in one scope. Flutter uses the first supported Material localization delegate in that scope.

Complete date-range picker example

Use rangePickerDelegate for Persian and Umm al-Qura ranges, together with matching calendar localizations. This function can be called from a button in an ordinary MaterialApp; the localization applies only to the dialog:

import 'package:flutter/material.dart';
import 'package:general_datetime/general_datetime.dart';
import 'package:general_datetime/delegates.dart';
import 'package:general_datetime/default_localizations.dart';

Future<DateTimeRange<DateTime>?> pickPersianRange(
  BuildContext context, {
  DateTimeRange<DateTime>? initialDateRange,
}) {
  final delegate = const PersianCalendarDelegate().rangePickerDelegate;
  return showDateRangePicker(
    context: context,
    firstDate: PersianDateTime(1400),
    lastDate: PersianDateTime(1410, 12, 29),
    initialDateRange: initialDateRange,
    calendarDelegate: delegate,
    builder: calendarDateRangePickerBuilder(
      delegate,
      builder: (context, child) => Localizations.override(
        context: context,
        locale: const Locale('en'),
        delegates: const [
          DefaultPersianCalendarMaterialLocalizations.delegate,
        ],
        child: child,
      ),
    ),
  );
}

For example, call await pickPersianRange(context) or pass DateTimeRange(start: PersianDateTime(1403, 1, 1), end: PersianDateTime(1403, 1, 5)) as initialDateRange. The result is null on cancellation. Otherwise, start and end are PersianDateTime objects, even though the return type uses DateTime. Save that result and pass it back when reopening the same calendar.

For Umm al-Qura, replace the dates with HijriDateTime, the delegate with const HijriCalendarDelegate().rangePickerDelegate, and the localization with DefaultHijriCalendarMaterialLocalizations.delegate. Keep bounds within the calendar's supported years. The example explicitly selects English because these built-in localizations only support en. For a translated picker, use the matching general_date_format localization delegate and a supported locale instead; configure the app's Flutter widget localizations for RTL languages.

Why the range-picker builder exists

calendarDateRangePickerBuilder is a Flutter compatibility helper. In Flutter 3.32.0's implementation, showDateRangePicker accepts calendarDelegate but does not pass it to the DateRangePickerDialog it creates. The dialog then uses its default Gregorian delegate. Wrapping that dialog in Localizations.override changes its labels and parsing, but does not replace its calendar arithmetic.

The helper supplies the missing delegate while preserving locale, text direction, and dialog options. Pass the same delegate instance to showDateRangePicker and calendarDateRangePickerBuilder. Put your Localizations.override, Theme, or other wrapper in the helper's optional builder argument, as shown above.

On Flutter SDKs that forward the delegate correctly, you can call showDateRangePicker directly with your localization builder:

// Use the same dates and delegate as in pickPersianRange above.
builder: (context, child) => Localizations.override(
  context: context,
  locale: const Locale('en'),
  delegates: const [DefaultPersianCalendarMaterialLocalizations.delegate],
  child: child,
),

The helper is optional on those SDKs and passes their dialog through unchanged. Keep it when your app or package must support Flutter 3.32; this package's minimum Flutter version is 3.32.0. If you construct DateRangePickerDialog yourself, pass calendarDelegate directly to its constructor and wrap it in the matching localizations; the compatibility helper is unnecessary.

Switching calendars and handling supported bounds

For an app-defined CalendarType enum, choose the range delegate like this:

final CalendarDelegate<DateTime> delegate = switch (widget.calendarType) {
  CalendarType.persian => const PersianCalendarDelegate().rangePickerDelegate,
  CalendarType.gregorian => const GregorianCalendarDelegate(),
};

Use that delegate with the builder pattern above, choosing the Persian localization only for the Persian branch and the app's ordinary Gregorian Material localizations for the Gregorian branch. An empty override delegate list inherits the app's localizations; this assumes the app has not globally installed a Persian or Hijri Material localization.

firstDate, lastDate, optional currentDate, and both initialDateRange endpoints must match the selected calendar's runtime type. Use native Gregorian DateTime values for Gregorian, PersianDateTime for Persian, and HijriDateTime for Umm al-Qura. On a calendar switch, explicitly convert saved dates to the new calendar or clear the initial range. For example, PersianDateTime.fromDateTime(gregorianDate) converts an instant; constructing PersianDateTime(gregorianDate.year, gregorianDate.month, gregorianDate.day) would instead interpret those numbers as Persian fields. Ensure the initial range is ordered and lies inside the picker bounds.

Flutter probes empty leading cells and adjacent keyboard targets before checking the picker's bounds. The adapter supplies native comparison dates for those probes; selectable dates and returned range endpoints remain supported calendar objects. Use the ordinary delegate for general date arithmetic and single-date pickers.

To display the earliest supported month, for example, use PersianDateTime(PersianDateTime.minimumYear) as both firstDate and currentDate, and a later supported Persian date as lastDate. The rangePickerDelegate adapter handles probes outside that boundary; it does not allow users to select dates outside the calendar's supported range.

Standalone year selection

Use Flutter's YearPicker and supply a matching currentDate. Its native default clock is Gregorian even with a custom calendar delegate:

Widget persianYears(BuildContext context, ValueChanged<DateTime> onChanged) {
  return Localizations.override(
    context: context,
    delegates: const [DefaultPersianCalendarMaterialLocalizations.delegate],
    child: YearPicker(
      firstDate: PersianDateTime(1380),
      lastDate: PersianDateTime(1450, 12, 29),
      selectedDate: PersianDateTime(1403, 1, 1),
      currentDate: PersianDateTime.now(),
      calendarDelegate: const PersianCalendarDelegate(),
      onChanged: onChanged,
    ),
  );
}

CalendarDatePicker already defaults its current date through the calendar delegate. This package exports no CalendarYearPicker wrapper.

Formatting and examples

Use the neighboring general_date_format / general_date_format_core packages for localized patterns, names, digits, and strict parsing. Chronology ISO-like output is intended for its matching calendar parser.

The calendar application demo uses timezone directly for named-zone event presentation and explicit missing/repeated wall-time policies. Timezone handling is local to the demo; the chronology packages have no zone dependency.

Development and testing

After resolving local dependencies, run from this repository:

flutter analyze
flutter test
flutter test test/unit/calendar_critical_test.dart test/unit/calendar_picker_critical_test.dart
dart format --output=none --set-exit-if-changed lib test example/lib

Run dart analyze and dart test inside the chronology core (resolve its dependencies first). Run flutter test in apps/calendar_demo. Both Dart cores include compilable CLI examples.

Tests compare all 1,183,020 supported Persian days and all 106,665 Umm al-Qura days against independent fixtures. Regressions cover leap/month boundaries, normalization and integer overflow, negative epochs, fractions, UTC/local/DST, equality/hash keys, field helpers, strict serialization, delegate guards, and picker input/navigation.

Local verification on 2026-10-05, using Flutter 3.47.5 / Dart 3.13.4:

Suite Passed
Flutter chronology/pickers 289
Standalone chronology core 20
Scheduling package 6
Calendar demo 8

Analysis and format checks passed. The core CLI compiled and ran, and explicit historical Tehran 23/25-hour assertions passed with:

flutter test --dart-define=CALENDAR_TEST_TZ=Asia/Tehran test/unit/calendar_critical_test.dart

CI is configured for minimum/current SDKs and UTC/Tehran/New York Linux jobs; dependencies resolve from pub.dev without local overrides. Windows local tests use the OS timezone. Browser JavaScript/Wasm, Android/iOS, minimum SDK execution, the full process-timezone matrix, and hosted dependency resolution were not certified by that local run. Coverage percentages were not recalculated.

Release dependency order is: general_datetime_core first, then general_datetime and general_date_format_core, then general_date_format. Before publishing wrappers, resolve and test the matching hosted core versions without development overrides. Local path success does not certify hosted resolution.

Contributions and license

See CHANGELOG.md for release changes. Open issues and pull requests on the repository. The code uses the BSD 3-Clause LICENSE; calendar data attribution and the Unicode license are in THIRD_PARTY_NOTICES.md.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages