{"id":25529090,"url":"https://github.com/boa-dev/temporal","last_synced_at":"2026-04-02T22:33:03.540Z","repository":{"id":221259894,"uuid":"753875367","full_name":"boa-dev/temporal","owner":"boa-dev","description":"A Rust implementation of ECMAScript's Temporal API","archived":false,"fork":false,"pushed_at":"2025-03-26T23:15:20.000Z","size":1364,"stargazers_count":42,"open_issues_count":45,"forks_count":15,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-28T09:09:00.998Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boa-dev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-Apache","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-07T00:22:20.000Z","updated_at":"2025-03-25T00:28:43.000Z","dependencies_parsed_at":"2024-05-28T19:30:51.715Z","dependency_job_id":"1f674912-3d48-43c1-8a09-60390a7ac4eb","html_url":"https://github.com/boa-dev/temporal","commit_stats":{"total_commits":83,"total_committers":7,"mean_commits":"11.857142857142858","dds":0.4457831325301205,"last_synced_commit":"454d1a8f5147643ff8838aea9c02df6fb4e661db"},"previous_names":["boa-dev/temporal"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boa-dev%2Ftemporal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boa-dev%2Ftemporal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boa-dev%2Ftemporal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boa-dev%2Ftemporal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boa-dev","download_url":"https://codeload.github.com/boa-dev/temporal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247305930,"owners_count":20917207,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-19T23:30:26.011Z","updated_at":"2026-04-02T22:33:03.533Z","avatar_url":"https://github.com/boa-dev.png","language":"Rust","readme":"# Temporal in Rust\n\n`temporal_rs` is a Rust date/time library that provides support for calendrical\ncalculations and time zones that is based on the Temporal specification.\n\nThis implementation aims to be 100% test compliant. While initially developed\nfor [Boa][boa-repo], the crate was split from the engine repository for general\nRust usage and vendoring to other ECMAScript implementations.\n\nFor more information on `temporal_rs`'s general position in the Rust date/time\nlibrary ecoystem or whether we may address your use case, see our\n[FAQ](./docs/FAQ.md).\n\nCurrently, `temporal_rs` is used in Boa, [Kiesel](https://codeberg.org/kiesel-js/kiesel),\nand [V8](https://v8.dev) for the core functionality of their Temporal built-ins.\n\n## Project overview\n\nThis project publishes the following crates:\n\n- [`temporal_rs`](https://docs.rs/temporal_rs/latest/temporal_rs/), the core date/time library\n- [`temporal_capi`](https://docs.rs/temporal_capi/latest/temporal_capi/), a FFI crate for C and C++\n- [`timezone_provider`](https://docs.rs/timezone_provider/latest/timezone_provider/), a time zone data provider crate\n- [`zoneinfo_rs`](https://docs.rs/zoneinfo_rs/latest/zoneinfo_rs/), an experimental zoneinfo compiler crate\n\n## Why use temporal_rs?\n\nTemporal is a date and time library that is both calendar and time zone aware manner. This\nmeans that calendar and time zone support are first class in Temporal.\n\nFor instance, converting between calendars is as simple as providing the calendar as\nshown below.\n\n```rust\nuse temporal_rs::{PlainDate, Calendar};\nuse tinystr::tinystr;\nuse core::str::FromStr;\n\n// Create a date with an ISO calendar\nlet iso8601_date = PlainDate::try_new_iso(2025, 3, 3).unwrap();\n\n// Create a new date with the japanese calendar\nlet japanese_date = iso8601_date.with_calendar(Calendar::JAPANESE);\nassert_eq!(japanese_date.era(), Some(tinystr!(16, \"reiwa\")));\nassert_eq!(japanese_date.era_year(), Some(7));\nassert_eq!(japanese_date.month(), 3)\n```\n\nBeyond the general calendar use case, temporal_rs has robust support for\ntime zones which can generally by applied to a `PlainDate` via [`ZonedDateTime`].\n\n**Important Note:** The below API is enabled with the\n`compiled_data` feature flag.\n\n```rust\nuse temporal_rs::{ZonedDateTime, TimeZone};\nuse temporal_rs::options::{Disambiguation, OffsetDisambiguation};\n\nlet zdt = ZonedDateTime::from_utf8(\nb\"2025-03-01T11:16:10Z[America/Chicago][u-ca=iso8601]\",\nDisambiguation::Compatible,\nOffsetDisambiguation::Reject\n).unwrap();\nassert_eq!(zdt.year(), 2025);\nassert_eq!(zdt.month(), 3);\nassert_eq!(zdt.day(), 1);\n// Using Z and a timezone projects a UTC datetime into the timezone.\nassert_eq!(zdt.hour(), 5);\nassert_eq!(zdt.minute(), 16);\nassert_eq!(zdt.second(), 10);\n\n// You can also update a time zone easily.\nlet zurich_zone = TimeZone::try_from_str(\"Europe/Zurich\").unwrap();\nlet zdt_zurich = zdt.with_timezone(zurich_zone).unwrap();\nassert_eq!(zdt_zurich.year(), 2025);\nassert_eq!(zdt_zurich.month(), 3);\nassert_eq!(zdt_zurich.day(), 1);\nassert_eq!(zdt_zurich.hour(), 12);\nassert_eq!(zdt_zurich.minute(), 16);\nassert_eq!(zdt_zurich.second(), 10);\n\n```\n\n## Library Overview\n\ntemporal_rs provides 8 core types for working with date and time. The core types are:\n\n- [PlainDate]\n- [PlainTime]\n- [PlainDateTime]\n- [ZonedDateTime]\n- [Instant]\n- [Duration]\n- [PlainYearMonth]\n- [PlainMonthDay]\n\nIn addition to these types, there are the [`Calendar`] and [`TimeZone`] type that\nsupport the calendars or time zones. The specific support for calendars and time\nzones per type are as follows.\n\n| Temporal type  | Category                             | Calendar support   | Time zone support  |\n|----------------|--------------------------------------|--------------------|--------------------|\n| PlainDate      | Calendar date                        |        yes         |         no         |\n| PlainTime      | Wall-clock time                      |        no          |         no         |\n| PlainDateTime  | Calendar date and wall-clock time    |        yes         |         no         |\n| ZonedDateTime  | Calendar date and exact time         |        yes         |        yes         |\n| Instant        | Exact time                           |        no          |         no         |\n| Duration       | None                                 |        no          |         no         |\n| PlainYearMonth | Calendar date                        |        yes         |         no         |\n| PlainMonthDay  | Calendar date                        |        yes         |         no         |\n\nThere is also the [`Now`][now::Now], which provides access to the current host system\ntime. This can then be used to map to any of the above Temporal types.\n\n**Important Note:** the below example is only available with the `sys` and\n`compiled_data` feature flag enabled.\n\n```rust\nuse core::cmp::Ordering;\nuse temporal_rs::{Temporal, Calendar, ZonedDateTime};\nlet current_instant = Temporal::now().instant().unwrap();\nlet current_zoned_date_time = Temporal::now().zoned_date_time_iso(None).unwrap();\n\n/// Create a `ZonedDateTime` from the requested instant.\nlet zoned_date_time_from_instant = ZonedDateTime::try_new(\ncurrent_instant.as_i128(),\n*current_zoned_date_time.time_zone(),\nCalendar::ISO,\n).unwrap();\n\n// The two `ZonedDateTime` will be equal down to the second.\nassert_eq!(current_zoned_date_time.year(), zoned_date_time_from_instant.year());\nassert_eq!(current_zoned_date_time.month(), zoned_date_time_from_instant.month());\nassert_eq!(current_zoned_date_time.day(), zoned_date_time_from_instant.day());\nassert_eq!(current_zoned_date_time.hour(), zoned_date_time_from_instant.hour());\nassert_eq!(current_zoned_date_time.minute(), zoned_date_time_from_instant.minute());\nassert_eq!(current_zoned_date_time.second(), zoned_date_time_from_instant.second());\n\n// The `Instant` reading that occurred first will be less than the ZonedDateTime\n// reading\nassert_eq!(\nzoned_date_time_from_instant.compare_instant(\u0026current_zoned_date_time),\nOrdering::Less\n);\n```\n\n## General design\n\nWhile temporal_rs can be used in native Rust programs, the library is -- first and\nforemost -- designed for use in ECMAScript implementations. This is not to detract\nfrom temporal_rs's use in a native Rust program, but it is important information to\nunderstand in order to understand the library's architecture and general API design.\n\nWithout default feature flags, temporal_rs is not released with access to the host\nenvironment and it does not embed any time zone data. This is important from an\ninterpreter perspective, because access to the host environment and time zone data\ncomes from the interpreter's agent, not from a dependency.\n\nInstead, temporal_rs provides the [`HostHooks`][host::HostHooks] and [`TimeZoneProvider`][provider::TimeZoneProvider]\ntraits that can be implemented and provided as function arguments that temporal_rs will\nuse to access the host system or time zone data. temporal_rs also provides some baseline\nimplementations of the traits that can be selected from depending on application needs.\n\nThat being said, this does not mean that everyone must implement their own trait\nimplementations for that functionality to exist, but the APIs are there for power\nusers who may need a custom host system or time zone data implementation.\n\nA default host system and time zone provider have been implemented and are automatically\nactive as default features. \n\n### A quick walkthrough\n\nFor instance, the examples thus far have been using the general usage Rust API with\nthe `sys` and `compiled_data` feature.\n\nFor instance, let's manually write our [`Now`][now::Now] implementation instead of using\n[`Temporal::now()`] with an empty host system implementation.\n\n```rust\nuse temporal_rs::{Instant, now::Now, host::EmptyHostSystem};\n\n// The empty host system is a system implementation HostHooks that always\n// returns the UNIX_EPOCH and the \"+00:00\" time zone.\nlet now = Now::new(EmptyHostSystem);\nlet time_zone = now.time_zone().unwrap();\nassert_eq!(time_zone.identifier().unwrap(), \"+00:00\");\nlet now = Now::new(EmptyHostSystem);\nassert_eq!(now.instant(), Instant::try_new(0));\n```\n\nHowever, even in our above example, we cheated a bit. We were still relying on the\n`compiled_data` feature flag that provided time zone data for us. Let's try again,\nbut this time without the feature flag.\n\n```rust\nuse temporal_rs::{Instant, now::Now, host::EmptyHostSystem};\nuse timezone_provider::tzif::CompiledTzdbProvider;\n\nlet provider = CompiledTzdbProvider::default();\n\n// The empty host system is a system implementation HostHooks that always\n// returns the UNIX_EPOCH and the \"+00:00\" time zone.\nlet now = Now::new(EmptyHostSystem);\nlet time_zone = now.time_zone_with_provider(\u0026provider).unwrap();\nassert_eq!(time_zone.identifier_with_provider(\u0026provider).unwrap(), \"+00:00\");\n\nlet now = Now::new(EmptyHostSystem);\nassert_eq!(now.instant(), Instant::try_new(0));\n```\n\nNow -- pun only partially intended -- we've successfully written a no-default-features\nexample with temporal_rs!\n\n### What have we learned going over this all this?\n\nFirst, any API that has the suffix `_with_provider` is a power user API for supplying\na custom or specific time zone data provider. Furthermore, any API that has a\n`_with_provider` suffix will also have a version without the suffix that automagically\nprovides time zone data for you.\n\nFinally, sourcing time zone data is a very scary (but fun!) business. If you're interested\nin learning more, feel free to check out the `timezone_provider` crate!\n\nWith any luck, this also highlights the general design of temporal_rs. It provides a\ngeneral usage API that aligns with the Temporal specification while also being\nflexible enough to provide an power user to take control of their host system access\nand time zone data sourcing as needed.\n\n## Formatting\n\ntemporal_rs adheres to Temporal grammar, which is a strict version of\n[RFC9557's IXDTF][ixdtf]. RFC9557 is an update to RFC3339 that adds\nextensions to the format. \n\n## More information\n\n[`Temporal`][proposal] is the Stage 4 proposal for ECMAScript that\nprovides new JS objects and functions for working with dates and\ntimes that fully supports time zones and non-gregorian calendars.\n\nThis library's primary development source is the Temporal\nProposal [specification][spec].\n\n## Temporal proposal\n\nRelevant links and information regarding Temporal can be found below.\n\n- [Temporal MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal)\n- [Temporal Documentation](https://tc39.es/proposal-temporal/docs/)\n- [Temporal Proposal Specification](https://tc39.es/proposal-temporal/)\n- [Temporal Proposal Repository](https://github.com/tc39/proposal-temporal)\n\n## Core maintainers\n\n- [Kevin Ness](https://github.com/nekevss)\n- [Manish Goregaokar](https://github.com/Manishearth)\n- [José Julián Espina](https://github.com/jedel1043)\n- [Jason Williams](https://github.com/jasonwilliams)\n- [Haled Odat](https://github.com/HalidOdat)\n- [Boa Developers](https://github.com/orgs/boa-dev/people)\n\n## Contributing\n\nThis project is open source and welcomes anyone interested to\nparticipate. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more\ninformation.\n\n## Test262 Conformance\n\n\u003c!-- TODO: Potentially update with tests if a runner can be implemented --\u003e\n\nThe `temporal_rs`'s current conformance results can be viewed on Boa's\n[test262 conformance page](https://boajs.dev/conformance).\n\n## FFI\n\n`temporal_rs` currently has bindings for C++, available via the\n`temporal_capi` crate.\n\n## Communication\n\nFeel free to contact us on\n[Matrix](https://matrix.to/#/#boa:matrix.org).\n\n## License\n\nThis project is licensed under the [Apache](./LICENSE-Apache) or\n[MIT](./LICENSE-MIT) licenses, at your option.\n\n[boa-repo]: https://github.com/boa-dev/boa\n[ixdtf]: https://www.rfc-editor.org/rfc/rfc9557.txt\n[proposal]: https://github.com/tc39/proposal-temporal\n[spec]: https://tc39.es/proposal-temporal/\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboa-dev%2Ftemporal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboa-dev%2Ftemporal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboa-dev%2Ftemporal/lists"}