Skip to content

Commit 83117dd

Browse files
Update tutorials (#6590)
They are not currently working with 2.0 code
1 parent 09d75a9 commit 83117dd

File tree

3 files changed

+74
-99
lines changed

3 files changed

+74
-99
lines changed

tutorials/date-picker-data.md

Lines changed: 43 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ Data generation is done using the `icu4x-datagen` tool, which pulls data from [U
1111
Verify that Rust is installed. If it's not, you can install it in a few seconds from [https://rustup.rs/](https://rustup.rs/).
1212

1313
```console
14-
$ cargo --version
15-
cargo 1.81.0 (2dbb1af80 2024-08-20)
14+
cargo --version
15+
# cargo 1.86.0 (adf9b6ad1 2025-02-28)
1616
```
1717

1818
Now you can run
@@ -26,7 +26,7 @@ cargo install icu4x-datagen
2626
We're ready to generate the data. We will use the blob format, and create a blob that will contain just Chakma data. At runtime we can then load it as needed.
2727

2828
```console
29-
$ icu4x-datagen --markers all --locales ccp --format blob --out ccp.blob
29+
icu4x-datagen --markers all --locales ccp --format blob --out ccp.blob
3030
```
3131

3232
This will generate a `ccp.blob` file containing data for Chakma.
@@ -41,7 +41,7 @@ This will generate a `ccp.blob` file containing data for Chakma.
4141
To use blob data, we will need to add the `icu_provider_blob` crate to our project:
4242

4343
```console
44-
cargo add icu_provider_blob
44+
cargo add icu_provider_blob --features alloc
4545
```
4646

4747
We also need to enable the `serde` feature on the `icu` crate to enable deserialization support:
@@ -58,29 +58,23 @@ locale is Chakma:
5858
use icu::locale::locale;
5959
use icu_provider_blob::BlobDataProvider;
6060

61-
// Just below the imports (fill in the path):
62-
const CCP_BLOB_PATH: &str = "<absolute path to ccp.blob>";
63-
64-
let datetime_formatter = if locale == locale!("ccp") {
61+
// replace the date_formatter creation
62+
let date_formatter = if locale == locale!("ccp") {
6563
println!("Using buffer provider");
6664

67-
let blob = std::fs::read(CCP_BLOB_PATH)
65+
let blob = std::fs::read("ccp.blob")
6866
.expect("blob should read successfully")
6967
.into();
7068

7169
let provider =
7270
BlobDataProvider::try_new_from_blob(blob).expect("deserialization should succeed");
7371

74-
DateTimeFormatter::try_new_with_buffer_provider(
75-
&provider,
76-
&(&locale).into(),
77-
Default::default(),
78-
)
79-
.expect("should have data for selected locale")
72+
DateTimeFormatter::try_new_with_buffer_provider(&provider, locale.into(), YMD::medium())
73+
.expect("should have data for selected locale")
8074
} else {
8175
// As before
82-
DateTimeFormatter::try_new(&(&locale).into(), Default::default())
83-
.expect("should have data for selected locale")
76+
DateTimeFormatter::try_new(locale.into(), YMD::medium())
77+
.expect("should have data for specified locale")
8478
};
8579
```
8680

@@ -106,22 +100,19 @@ function load_blob(url, callback) {
106100

107101
if (localeStr == "ccp") {
108102
load_blob("https://storage.googleapis.com/static-493776/icu4x_2023-11-03/ccp.blob", (blob) => {
109-
let dateTimeFormatter = ICU4XDateTimeFormatter.create_with_lengths(
110-
ICU4XDataProvider.create_from_byte_slice(blob),
103+
let dateTimeFormatter = DateTimeFormatter.createYmdtWithProvider(
104+
DataProvider.createFromBlob(blob),
111105
locale,
112-
ICU4XDateLength.Medium,
113-
ICU4XTimeLength.Medium,
106+
DateTimeLength.Long,
114107
);
115-
document.getElementById("output").innerText = dateFormatter.format_iso_datetime(isoDateTime);
108+
document.getElementById("output").innerText = dateTimeFormatter.formatIso(isoDate, time);
116109
})
117110
} else {
118-
let dateTimeFormatter = ICU4XDateTimeFormatter.create_with_lengths(
119-
ICU4XDataProvider.create_compiled(),
120-
locale,
121-
ICU4XDateLength.Medium,
122-
ICU4XTimeLength.Medium,
111+
let dateTimeFormatter = DateTimeFormatter.createYmdt(
112+
locale,
113+
DateTimeLength.Long,
123114
);
124-
document.getElementById("output").innerText = dateFormatter.format_iso_datetime(isoDateTime);
115+
document.getElementById("output").innerText = dateTimeFormatter.formatIso(isoDate, time);
125116
}
126117
```
127118

@@ -134,67 +125,62 @@ Note: the following steps are currently only possible in Rust. 🤷
134125
When we ran `icu4x-datagen`, we passed `--markers all`, which make it generate *all* data for the Chakma locale, even though we only need date formatting. We can make `icu4x-datagen` analyze our binary to figure out which markers are needed:
135126

136127
```console
137-
$ icu4x-datagen --markers-for-bin target/debug/tutorial --locales ccp --format blob --out ccp_smaller.blob
128+
cargo build --release
129+
icu4x-datagen --markers-for-bin target/release/tutorial --locales ccp --format blob --out ccp_smaller.blob
138130
```
139131

140-
Note: you usually want to build with the `--release` flag, and analyze that binary, but we don't have all day.
132+
Note: you usually want to build with the `--release` flag, and analyze that binary.
141133

142134
This should generate a lot fewer markers!
143135

144136
Let's look at the sizes:
145137

146138
```console
147-
$ wc -c *.blob
148-
656767 ccp.blob
149-
45471 ccp_smaller.blob
139+
wc -c *.blob
140+
# 5448603 ccp.blob
141+
# 13711 ccp_smaller.blob
150142
```
151143

152144
This is much better! Rerun your app with `ccp_smaller.blob` to make sure it still works!
153145

154146
## 5. Slimming the data pack ... again
155147

156-
The last datagen invocation still produced a lot of markers, as you saw in its output. This is because we used the `DateFormatter` API, which can format dates for a lot of different calendars. However, if we are only using it with an Gregorian calendar date, so we don't need Coptic, Indian, etc. date formatting data.
148+
The last datagen invocation still produced a lot of markers, as you saw in its output. This is because we used the `DateTimeFormatter` API, which can format dates for a lot of different calendars (remember `en-u-ca-hebrew`). However, if we were only using it with a Gregorian calendar date, we wouldn't need Coptic, Indian, etc. date formatting data. Now, how do we communicate this to `--markers-for-bin`? Turns out, `icu::datetime` also exposes a `FixedCalendarDateTimeFormatter`, which is generic in a single calendar type. If you use this API instead, `--markers-for-bin` will only include the markers for that one calendar type.
157149

158-
We've seen that `DateFormatter` pulls in a lot of data. It would be nice if we could tell it that we'll only ever use it with Gregorian dates. Turns out we can! `icu::datetime` also exposes a `TypedDateFormatter<C>`, which is generic in a single calendar type. If you use this API instead (instantiated as `TypedDateFormatter<Gregorian>`), `--markers-for-bin` will give you exactly the markers we manually selected in the last section. However, now you can be sure that you didn't make a mistake selecting the markers (which would be an awkward runtime error), and that you will never accidentally pass a non-Gregorian date into the formatter (which would an awkward runtime error with `DateFormatter`, but is a compile-time error with `TypeDateFormatter`).
150+
Replace the `DateTimeFormatter::try_new` calls with `FixedCalendarDateTimeFormatter::try_new`, and change the `format` invocation to convert the input to the Gregorian calendar:
159151

160152
```rust
161-
let date_formatter = TypedDateFormatter::<Gregorian>::try_new_with_length(
162-
&(&locale).into(),
163-
length::Date::Medium,
164-
)
165-
.expect("should have data for selected locale");
166-
167-
println!(
168-
"Date: {}",
169-
// We need to convert to the explicit calendar via `.to_calendar()`.
170-
date_formatter.format(&iso_date.to_calendar(Gregorian)),
171-
);
153+
println!("Date: {}", date_formatter.format(&iso_date.to_calendar(Gregorian)));
172154
```
173155

156+
The generic type of `FixedCalendarDateTimeFormatter` will be inferred from the input, which now has type `&Date<Gregorian>` now. Unlike `DateTimeFormatter`, `FixedCalendarDateTimeFormatter` never applies calendar conversions on its input, so it will be a `FixedCalendarDateTimeFormatter<Gregorian, ...>`.
157+
174158
Now we can run datagen with `--markers-for-bin` again:
175159

176160
```console
177-
$ cargo build
178-
$ icu4x-datagen --markers-for-bin target/debug/tutorial --locales ccp --format blob --out ccp_smallest.blob
161+
cargo build --release
162+
icu4x-datagen --markers-for-bin target/release/tutorial --locales ccp --format blob --out ccp_smallest.blob
179163
```
180164

181165
The output will be much shorter:
182166

183167
```console
184-
INFO [icu_provider_export::export_impl] Generating marker datetime/gregory/datelengths@1
185-
INFO [icu_provider_export::export_impl] Generating marker datetime/gregory/datesymbols@1
186-
INFO [icu_provider_export::export_impl] Generating marker datetime/week_data@1
187-
INFO [icu_provider_export::export_impl] Generating marker decimal/symbols@2
188-
INFO [icu_provider_export::export_impl] Generating marker plurals/ordinal@1
168+
2025-05-14T14:26:52.306Z INFO [icu_provider_export::export_impl] Generated marker DatetimeNamesMonthGregorianV1
169+
2025-05-14T14:26:52.308Z INFO [icu_provider_export::export_impl] Generated marker DatetimeNamesYearGregorianV1
170+
2025-05-14T14:26:52.312Z INFO [icu_provider_export::export_impl] Generated marker DatetimePatternsDateGregorianV1
171+
2025-05-14T14:26:52.324Z INFO [icu_provider_export::export_impl] Generated marker DecimalDigitsV1
172+
2025-05-14T14:26:52.325Z INFO [icu_provider_export::export_impl] Generated marker DecimalSymbolsV1
189173
```
190174

191175
And the blob will also be much smaller at the sizes:
192176

193177
```console
194-
$ wc -c *.blob
195-
656767 ccp.blob
196-
45471 ccp_smaller.blob
197-
4639 ccp_smallest.blob
178+
wc -c *.blob
179+
# 5448603 ccp.blob
180+
# 13711 ccp_smaller.blob
181+
# 4711 ccp_smallest.blob
198182
```
199183

200184
Rerun your app with `ccp_smallest.blob` to make sure it still works!
185+
186+
Does the locale `en-u-ca-hebrew` still use the Hebrew calendar? Why is that?

tutorials/date-picker.md

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Verify that Rust is installed. If it's not, you can install it in a few seconds
1414

1515
```console
1616
cargo --version
17-
# cargo 1.81.0 (2dbb1af80 2024-08-20)
17+
# cargo 1.86.0 (adf9b6ad1 2025-02-28)
1818
```
1919

2020
Create a new Rust binary crate with icu4x as a dependency:
@@ -30,7 +30,7 @@ cargo add icu
3030
We recommend using [CodePen](https://codepen.io/pen/?editors=1011) to follow along. To load ICU4X into CodePen, you can use this snippet in the JavaScript editor:
3131

3232
```javascript
33-
import { ICU4XLocale, ICU4XDataProvider, ICU4XDateFormatter, ICU4XDateTimeFormatter, ICU4XDateLength, ICU4XIsoDate, ICU4XIsoDateTime, ICU4XTimeLength } from "https://storage.googleapis.com/static-493776/icu4x_2023-11-03/js/index.js";
33+
import { Locale, DateFormatter, IsoDate, DateTimeLength } from "https://storage.googleapis.com/static-493776/2_0/npm/lib/index.mjs";
3434
```
3535

3636
This loads the full development ICU4X WebAssembly file. Since it may take some time to load on slow connections, we'll create a loading div. In future tutorials you will learn how to build an optimized WebAssembly file, reducing the size of the WASM file by 99% or more. Add this to your HTML:
@@ -86,8 +86,8 @@ let locale = match locale_str.trim().parse::<Locale>() {
8686
Try inputting locales in non-canonical syntax and see them normalized!
8787

8888
```bash
89-
$ cargo run
90-
Enter your locale: DE_CH
89+
cargo run
90+
Enter your locale: DE-CH
9191
You entered: de-CH
9292
```
9393

@@ -108,10 +108,13 @@ And in JavaScript:
108108
function update() {
109109
try {
110110
let localeStr = document.getElementById("localeinput").value;
111-
let locale = ICU4XLocale.create_from_string(localeStr);
112-
document.getElementById("output").innerText = locale.to_string();
111+
112+
let locale = Locale.fromString(localeStr);
113+
let output = locale.toString();
114+
115+
document.getElementById("output").innerText = output;
113116
} catch(e) {
114-
document.getElementById("output").innerText = e + ": " + e.error_value;
117+
document.getElementById("output").innerText = e;
115118
}
116119
}
117120

@@ -124,7 +127,7 @@ update();
124127

125128
Try inputting locales in non-canonical syntax and see them normalized!
126129

127-
> Locale: ES_419\
130+
> Locale: ES-419
128131
> Output: es-419
129132
130133
## 3. Formatting a Date
@@ -136,35 +139,31 @@ Now we will use built-in locale data to produce a formatted date.
136139
We would like to format today's date. We will get this from the `time` crate, which you need to add:
137140

138141
```console
139-
$ cargo add time --features local-offset
142+
cargo add time --features local-offset
140143
```
141144

142145
Now we can write the Rust code:
143146

144147
```rust
145148
// At the top of the file:
146-
use icu::calendar::{Date, Iso};
147-
use icu::datetime::{DateTimeFormatter, fieldsets::YMD};
149+
use icu::datetime::{DateTimeFormatter, fieldsets::YMD, input::Date};
148150

149151
let locale = icu::locale::Locale::UNKNOWN; // to make this example compile
150152

151-
/// Helper function to create an ICU4X DateTime for the current local time:
152-
fn get_current_date() -> Date<Iso> {
153+
// Put the following in the main() function:
154+
let iso_date = {
153155
let current_offset_date_time = time::OffsetDateTime::now_local().unwrap();
154156
Date::try_new_iso(
155157
current_offset_date_time.year(),
156158
current_offset_date_time.month() as u8,
157159
current_offset_date_time.day(),
158160
)
159161
.unwrap()
160-
}
161-
162-
// Put the following in the main() function:
163-
let iso_date = get_current_date();
162+
};
164163

165164
// Create and use an ICU4X date formatter:
166165
let date_formatter = DateTimeFormatter::try_new(
167-
(&locale).into(),
166+
locale.into(),
168167
YMD::medium(),
169168
)
170169
.expect("should have data for specified locale");
@@ -194,25 +193,15 @@ And this to JavaScript:
194193
// Run the function whenever the date input changes:
195194
document.getElementById("dateinput").addEventListener("input", update, false);
196195

197-
/// Helper function to convert the date input to an ICU4X Date:
198-
function getDateFromInput() {
199-
let dateStr = document.getElementById("dateinput").value;
200-
let dateObj = dateStr ? new Date(dateStr) : new Date();
201-
return ICU4XIsoDate.create(
202-
dateObj.getYear() + 1900,
203-
dateObj.getMonth() + 1,
204-
dateObj.getDate(),
205-
);
206-
}
207-
208196
// Put the following in the update() function, inside the try block:
209-
let isoDate = getDateFromInput();
210-
let dateFormatter = ICU4XDateFormatter.create_with_length(
211-
ICU4XDataProvider.create_compiled(), // we will learn what this means later
212-
locale,
213-
ICU4XDateLength.Medium,
214-
);
215-
document.getElementById("output").innerText = dateFormatter.format_iso_date(isoDate);
197+
let dateStr = document.getElementById("dateinput").value;
198+
199+
let dateObj = dateStr ? new Date(dateStr) : new Date();
200+
let isoDate = new IsoDate(dateObj.getFullYear(), dateObj.getMonth() + 1, dateObj.getDate());
201+
let dateFormatter = DateFormatter.createYmd(locale, DateTimeLength.Long);
202+
let output = dateFormatter.formatIso(isoDate);
203+
204+
document.getElementById("output").innerText = output;
216205
```
217206

218207
Try this in several locales, like `en` (English), `en-GB` (British English), and `th` (Thai). Observe how differently dates are represented in locales around the world! You can explicitly specify arbitrary calendar systems using the `u-ca` Unicode extension keyword in the locale. Try `en-u-ca-hebrew`!
@@ -223,22 +212,22 @@ Now we would also like to format the current time.
223212

224213
### Rust Part 4
225214

226-
Use the API documentation for [`icu::time::DateTime`](https://docs.rs/icu/latest/icu/timezone/struct.DateTime.html) and [`icu::datetime::DateTimeFormatter`](https://docs.rs/icu/latest/icu/datetime/struct.DateTimeFormatter.html) to expand your app to format both date and time.
227-
228-
Hint: You can use `Default::default()` for the `DateTimeFormatterOptions` argument.
215+
Use the API documentation for [`icu::time::DateTime`](https://docs.rs/icu/latest/icu/time/struct.DateTime.html) and [`icu::datetime::fieldsets`](https://docs.rs/icu/latest/icu/datetime/fieldsets/index.html) to expand your app to format both date and time.
229216

230217
### JavaScript Part 4
231218

232-
Use the API documentation for [`ICU4XDateTime`](https://unicode-org.github.io/icu4x/tsdoc/classes/ICU4XDateTime.html) and [`ICU4XDateTimeFormatter`](https://unicode-org.github.io/icu4x/tsdoc/classes/ICU4XDateTimeFormatter.html) to expand your app to format both a date and a time.
219+
Use the API documentation for [`Time`](https://icu4x.unicode.org/2_0/tsdoc/classes/Time.html) and [`DateTimeFormatter`](https://icu4x.unicode.org/2_0/tsdoc/classes/DateTimeFormatter.html) to expand your app to format both a date and a time.
233220

234221
Hint: You can create an HTML time picker with
235222

236223
```html
237-
<input type="time" id="timeinput" value="10:10"/>
224+
<p><label>Time: <input type="time" id="timeinput" value="10:10"/></label></p>
238225
```
239226

240227
Hint: You can create a `Date` from `dateStr` and `timeStr` with
241228

242229
```javascript
243230
let dateObj = dateStr && timeStr ? new Date(dateStr + " " + timeStr) : new Date();
244231
```
232+
233+
Note that Dates constructed this way will be in UTC.

tutorials/quickstart.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ To verify that, open a terminal and check that the results are similar to:
1717

1818
```console
1919
cargo --version
20-
cargo 1.81.0 (2dbb1af80 2024-08-20)
20+
# cargo 1.86.0 (adf9b6ad1 2025-02-28)
2121
```
2222

2323
## 2. Creating an app with ICU4X as a dependency

0 commit comments

Comments
 (0)