diff --git a/Cargo.lock b/Cargo.lock index a370f25e6..b8c8de055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -316,9 +316,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "calendrical_calculations" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec493b209a1b81fa32312d7ceca1b547d341c7b5f16a3edbf32b1d8b455bbdf" +checksum = "9f6df87e869fb08be61c7e97ced8e69ab802df1d8bc612ed67dba78c07fbc12c" dependencies = [ "core_maths", "displaydoc", @@ -779,9 +779,9 @@ dependencies = [ [[package]] name = "fixed_decimal" -version = "0.5.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0febbeb1118a9ecdee6e4520ead6b54882e843dd0592ad233247dbee84c53db8" +checksum = "35943d22b2f19c0cb198ecf915910a8158e94541c89dcc63300d7799d46c2c5e" dependencies = [ "displaydoc", "smallvec", @@ -1187,9 +1187,8 @@ dependencies = [ "glob", "iana-time-zone", "icalendar", - "icu_calendar", "icu_datetime", - "icu_locid", + "icu_locale_core", "indexmap", "inotify", "itertools 0.13.0", @@ -1266,16 +1265,17 @@ dependencies = [ [[package]] name = "icu_calendar" -version = "1.5.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7265b2137f9a36f7634a308d91f984574bbdba8cfd95ceffe1c345552275a8ff" +checksum = "8e239d6422e2fdcea5d9756b48400caabac25aa4ab91b6608bd4bb6f23f0558c" dependencies = [ "calendrical_calculations", "displaydoc", "icu_calendar_data", - "icu_locid", - "icu_locid_transform", + "icu_locale", + "icu_locale_core", "icu_provider", + "ixdtf", "tinystr", "writeable", "zerovec", @@ -1283,17 +1283,18 @@ dependencies = [ [[package]] name = "icu_calendar_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e009b7f0151ee6fb28c40b1283594397e0b7183820793e9ace3dcd13db126d0" +checksum = "7219c8639ab936713a87b571eed2bc2615aa9137e8af6eb221446ee5644acc18" [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", @@ -1301,9 +1302,9 @@ dependencies = [ [[package]] name = "icu_datetime" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d115efb85e08df3fd77e77f52e7e087545a783fffba8be80bfa2102f306b1780" +checksum = "0790c15e3d6ae3303365fa2337b4f6469de257916141110d14dcaf73f1d31ac5" dependencies = [ "displaydoc", "either", @@ -1311,11 +1312,13 @@ dependencies = [ "icu_calendar", "icu_datetime_data", "icu_decimal", - "icu_locid", - "icu_locid_transform", + "icu_locale", + "icu_locale_core", + "icu_pattern", "icu_plurals", "icu_provider", - "icu_timezone", + "icu_time", + "potential_utf", "smallvec", "tinystr", "writeable", @@ -1324,68 +1327,73 @@ dependencies = [ [[package]] name = "icu_datetime_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba7e7f7a01269b9afb0a39eff4f8676f693b55f509b3120e43a0350a9f88bea" +checksum = "83791ac10bb7b774f130bb81fa89c4059de710dcef53caa0b86e645212d6d54c" [[package]] name = "icu_decimal" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8fd98f86ec0448d85e1edf8884e4e318bb2e121bd733ec929a05c0a5e8b0eb" +checksum = "fec61c43fdc4e368a9f450272833123a8ef0d7083a44597660ce94d791b8a2e2" dependencies = [ "displaydoc", "fixed_decimal", "icu_decimal_data", - "icu_locid_transform", + "icu_locale", + "icu_locale_core", "icu_provider", + "tinystr", "writeable", + "zerovec", ] [[package]] name = "icu_decimal_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d424c994071c6f5644f999925fc868c85fec82295326e75ad5017bc94b41523" +checksum = "b70963bc35f9bdf1bc66a5c1f458f4991c1dc71760e00fa06016b2c76b2738d5" [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd" dependencies = [ "displaydoc", - "litemap", + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "potential_utf", "tinystr", - "writeable", "zerovec", ] [[package]] -name = "icu_locid_transform" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", + "litemap", "tinystr", + "writeable", "zerovec", ] [[package]] -name = "icu_locid_transform_data" -version = "1.5.0" +name = "icu_locale_data" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765" [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -1393,27 +1401,36 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_pattern" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983825f401e6bc4a13c45d552ffd9ad6f3f6b6bc0ec03f31d6835a90a46deb1f" +dependencies = [ + "displaydoc", + "either", + "writeable", + "zerovec", +] [[package]] name = "icu_plurals" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a70e7c025dbd5c501b0a5c188cd11666a424f0dadcd4f0a95b7dafde3b114" +checksum = "0fd83a65f58b6f28e1f3da8c6ada6b415ee3ad5cb480b75bdb669f34d72dd179" dependencies = [ "displaydoc", "fixed_decimal", - "icu_locid_transform", + "icu_locale", "icu_plurals_data", "icu_provider", "zerovec", @@ -1421,79 +1438,74 @@ dependencies = [ [[package]] name = "icu_plurals_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3e8f775b215d45838814a090a2227247a7431d74e9156407d9c37f6ef0f208" +checksum = "9ec552d761eaf4a1c39ad28936e0af77a41bf01ff756ea54be4f8bfc21c265d7" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] [[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - -[[package]] -name = "icu_timezone" -version = "1.5.0" +name = "icu_time" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa91ba6a585939a020c787235daa8aee856d9bceebd6355e283c0c310bc6de96" +checksum = "10d01a4a2dcbc5e5180ef113920e7461d0e9caaddb3567d81c4eca262efe55c0" dependencies = [ + "calendrical_calculations", "displaydoc", "icu_calendar", + "icu_locale_core", "icu_provider", - "icu_timezone_data", + "icu_time_data", + "ixdtf", + "serde", "tinystr", + "writeable", "zerotrie", "zerovec", ] [[package]] -name = "icu_timezone_data" -version = "1.5.0" +name = "icu_time_data" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c588878c508a3e2ace333b3c50296053e6483c6a7541251b546cc59dcd6ced8e" +checksum = "8472be4410d26a03d7208cae3a76c798dd6766e8226ab977cd8b2d349a6dbf08" [[package]] name = "ident_case" @@ -1514,9 +1526,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -1610,6 +1622,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "ixdtf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8289f7f711a1a51f80e2e368355d023042ca55d8d554fd5e953f01464c15842d" +dependencies = [ + "displaydoc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -1665,7 +1686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1754,9 +1775,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "log" @@ -2210,6 +2231,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "serde", + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -2902,9 +2933,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -3142,12 +3173,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -3565,17 +3590,14 @@ dependencies = [ "memchr", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +dependencies = [ + "either", +] [[package]] name = "x11rb" @@ -3642,9 +3664,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -3654,9 +3676,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", @@ -3771,9 +3793,9 @@ checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zerotrie" -version = "0.1.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb594dd55d87335c5f60177cee24f19457a5ec10a065e0a3014722ad252d0a1f" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ "displaydoc", "yoke", @@ -3782,9 +3804,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", @@ -3793,9 +3815,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index f78736aa7..8a0ffab62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ pulseaudio = ["libpulse-binding"] pipewire = ["dep:pipewire"] notmuch = ["dep:notmuch"] maildir = ["dep:maildir", "glob"] -icu_calendar = ["dep:icu_datetime", "dep:icu_calendar", "dep:icu_locid"] +icu_calendar = ["dep:icu_datetime", "dep:icu_locale_core"] debug_borders = [] # Make widgets' borders visible [package.metadata.docs.rs] @@ -43,9 +43,8 @@ futures = { version = "0.3.31", default-features = false } glob = { version = "0.3.1", optional = true } iana-time-zone = "0.1.60" icalendar = { version = "0.16.2", features = ["chrono-tz"] } -icu_calendar = { version = "1.3.0", optional = true } -icu_datetime = { version = "1.3.0", optional = true } -icu_locid = { version = "1.3.0", optional = true } +icu_datetime = { version = "2.0.0", optional = true } +icu_locale_core = { version = "2.0.0", optional = true } indexmap = { version = "2.0", features = ["serde"] } inotify = "0.11" itertools = "0.13" diff --git a/cspell.yaml b/cspell.yaml index 80a7b3bb2..16eebf64f 100644 --- a/cspell.yaml +++ b/cspell.yaml @@ -193,6 +193,9 @@ words: - xrandr - xresources - xtask + - YMDE + - YMDET + - YMDT - zbus - zram - zswap diff --git a/src/blocks/time.rs b/src/blocks/time.rs index 4f0fca5da..e645a9da2 100644 --- a/src/blocks/time.rs +++ b/src/blocks/time.rs @@ -34,6 +34,7 @@ //! You can use calendars other than the Gregorian calendar by adding the calendar specifier in the locale string. When using //! this feature you can't use chrono style format string, and you should use one of the options provided by //! the `icu4x` crate: `short`, `medium`, `long`, `full`. +//! If you set `precision` to `hours`/`hour`/`h`, `minutes`/`minute`/`m`, or `seconds`/`second`/`s` then then the datetime will be formatted accordingly, otherwise only the date with be displayed. //! //! ** Only available using feature `icu_calendar`. ** //! @@ -43,7 +44,7 @@ //! [[block]] //! block = "time" //! interval = 60 -//! format = "$timestamp.datetime(locale:'fa_IR-u-ca-persian', f:'full')" +//! format = "$timestamp.datetime(locale:'fa_IR-u-ca-persian', f:'full', precision: minutes)" //! ``` //! //! # Icons Used diff --git a/src/formatting.rs b/src/formatting.rs index 8468b2f66..407005a5b 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -79,11 +79,11 @@ //! No arguments. //! //! ## `datetime` - Display datetime -//! -//! Argument | Description |Default value -//! -----------------------|-----------------------------------------------------------------------------------------------------------|------------- -//! `format` or `f` | [chrono docs](https://docs.rs/chrono/0.3.0/chrono/format/strftime/index.html#specifiers) for all options. | `'%a %d/%m %R'` -//! `locale` or `l` | Locale to apply when formatting the time | System locale +//! Argument | Description |Default value +//! -----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------- +//! `format` or `f` | [chrono docs](https://docs.rs/chrono/0.3.0/chrono/format/strftime/index.html#specifiers) for all options, or `short`, `medium`, `long`, or `full` for icu datetimes | `'%a %d/%m %R'` +//! `locale` or `l` | Locale to apply when formatting the time | System locale +//! `precision` or `p` | Precision to apply when formatting an icu datetime (`hours`/`hour`/`h`, `minutes`/`minute`/`m`, or `seconds`/`second`/`s`), if none is specified then only the date will be displayed | None //! //! //! ## `duration`/`dur` - Format durations diff --git a/src/formatting/formatter/datetime.rs b/src/formatting/formatter/datetime.rs index 77a336163..95ba4e2df 100644 --- a/src/formatting/formatter/datetime.rs +++ b/src/formatting/formatter/datetime.rs @@ -12,7 +12,7 @@ make_log_macro!(error, "datetime"); const DEFAULT_DATETIME_FORMAT: &str = "%a %d/%m %R"; pub static DEFAULT_DATETIME_FORMATTER: LazyLock = - LazyLock::new(|| DatetimeFormatter::new(Some(DEFAULT_DATETIME_FORMAT), None).unwrap()); + LazyLock::new(|| DatetimeFormatter::new(Some(DEFAULT_DATETIME_FORMAT), None, None).unwrap()); #[derive(Debug)] pub enum DatetimeFormatter { @@ -22,8 +22,8 @@ pub enum DatetimeFormatter { }, #[cfg(feature = "icu_calendar")] Icu { - length: icu_datetime::options::length::Date, - locale: icu_locid::Locale, + fieldset: icu_datetime::fieldsets::enums::CompositeDateTimeFieldSet, + locale: icu_locale_core::Locale, }, } @@ -31,6 +31,7 @@ impl DatetimeFormatter { pub(super) fn from_args(args: &[Arg]) -> Result { let mut format = None; let mut locale = None; + let mut precision = None; for arg in args { match arg.key { "format" | "f" => { @@ -39,6 +40,9 @@ impl DatetimeFormatter { "locale" | "l" => { locale = Some(arg.val.error("locale must be specified")?); } + "precision" | "p" => { + precision = Some(arg.val.error("precision must be specified")?); + } other => { return Err(Error::new(format!( "Unknown argument for 'datetime': '{other}'" @@ -46,30 +50,73 @@ impl DatetimeFormatter { } } } - Self::new(format, locale) + Self::new(format, locale, precision) } - fn new(format: Option<&str>, locale: Option<&str>) -> Result { + fn new(format: Option<&str>, locale: Option<&str>, precision: Option<&str>) -> Result { let (items, locale) = match locale { Some(locale) => { #[cfg(feature = "icu_calendar")] let Ok(locale) = locale.try_into() else { - use std::str::FromStr as _; // try with icu4x - let locale = icu_locid::Locale::from_str(locale) + use icu_datetime::fieldsets::{ + self, + enums::{CompositeDateTimeFieldSet, DateAndTimeFieldSet, DateFieldSet}, + }; + use icu_datetime::options::{Length, TimePrecision}; + use std::str::FromStr as _; + + let precision = match precision { + Some("seconds" | "second" | "s") => Some(TimePrecision::Second), + Some("minutes" | "minute" | "m") => Some(TimePrecision::Minute), + Some("hours" | "hour" | "h") => Some(TimePrecision::Hour), + None => None, + _ => Err(Error::new("Invalid precision value"))?, + }; + let locale = icu_locale_core::Locale::from_str(locale) .ok() .error("invalid locale")?; - let length = match format { - Some("full") => icu_datetime::options::length::Date::Full, - None | Some("long") => icu_datetime::options::length::Date::Long, - Some("medium") => icu_datetime::options::length::Date::Medium, - Some("short") => icu_datetime::options::length::Date::Short, - _ => return Err(Error::new("Unknown format option for icu based locale")), + let fieldset = match format { + Some("full") => match precision { + Some(precision) => { + CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::YMDET( + fieldsets::YMDET::long().with_time_precision(precision), + )) + } + None => CompositeDateTimeFieldSet::Date(DateFieldSet::YMDE( + fieldsets::YMDE::long(), + )), + }, + length => { + let length = match length { + Some("short") => Length::Short, + Some("medium") => Length::Medium, + Some("long") | None => Length::Long, + _ => Err(Error::new("Invalid length value"))?, + }; + match precision { + Some(precision) => { + CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::YMDT( + fieldsets::YMDT::for_length(length) + .with_time_precision(precision), + )) + } + None => CompositeDateTimeFieldSet::Date(DateFieldSet::YMD( + fieldsets::YMD::for_length(length), + )), + } + } }; - return Ok(Self::Icu { locale, length }); + + return Ok(Self::Icu { locale, fieldset }); }; #[cfg(not(feature = "icu_calendar"))] let locale = locale.try_into().ok().error("invalid locale")?; + if precision.is_some() { + return Err(Error::new( + "`precision` is only available for icu datetimes", + )); + } ( StrftimeItems::new_with_locale( format.unwrap_or(DEFAULT_DATETIME_FORMAT), @@ -78,10 +125,17 @@ impl DatetimeFormatter { Some(locale), ) } - None => ( - StrftimeItems::new(format.unwrap_or(DEFAULT_DATETIME_FORMAT)), - None, - ), + None => { + if precision.is_some() { + return Err(Error::new( + "`precision` is only available for icu datetimes", + )); + } + ( + StrftimeItems::new(format.unwrap_or(DEFAULT_DATETIME_FORMAT)), + None, + ) + } }; Ok(Self::Chrono { @@ -164,23 +218,30 @@ impl Formatter for DatetimeFormatter { } } #[cfg(feature = "icu_calendar")] - DatetimeFormatter::Icu { locale, length } => { - use chrono::Datelike as _; - let date = icu_calendar::Date::try_new_iso_date( - datetime.year(), - datetime.month() as u8, - datetime.day() as u8, - ) - .ok() - .error("Current date should be a valid date")?; - let date = date.to_any(); - let dft = - icu_datetime::DateFormatter::try_new_with_length(&locale.into(), *length) - .ok() - .error("locale should be present in compiled data")?; - dft.format_to_string(&date) + DatetimeFormatter::Icu { + locale, + fieldset: length, + } => { + use chrono::{Datelike as _, Timelike as _}; + let datetime = icu_datetime::input::DateTime { + date: icu_datetime::input::Date::try_new_iso( + datetime.year(), + datetime.month() as u8, + datetime.day() as u8, + ) + .error("Current date should be a valid date")?, + time: icu_datetime::input::Time::try_new( + datetime.hour() as u8, + datetime.minute() as u8, + datetime.second() as u8, + datetime.nanosecond(), + ) + .error("Current time should be a valid time")?, + }; + let dft = icu_datetime::DateTimeFormatter::try_new(locale.into(), *length) .ok() - .error("formatting date using icu failed")? + .error("locale should be present in compiled data")?; + dft.format(&datetime).to_string() } }) }