or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

calendar-system.mdcurrent-time.mddate-time-classes.mdduration-arithmetic.mdindex.mdinstant-zoned-datetime.mdintl-formatting.md

intl-formatting.mddocs/

0

# International Formatting

1

2

Enhanced `Intl.DateTimeFormat` class with native Temporal type support for formatting dates and times. Provides seamless integration between Temporal objects and internationalization features.

3

4

## Capabilities

5

6

### Enhanced DateTimeFormat

7

8

Extended version of `Intl.DateTimeFormat` that supports all Temporal types in addition to legacy Date objects.

9

10

```typescript { .api }

11

/**

12

* Enhanced DateTimeFormat class supporting Temporal types

13

*/

14

class DateTimeFormat extends Intl.DateTimeFormat {

15

/** Creates a new DateTimeFormat instance */

16

constructor(locales?: LocalesArgument, options?: Intl.DateTimeFormatOptions);

17

18

/** Formats a Temporal object or Date as a string */

19

format(date: TemporalFormattable | Date): string;

20

21

/** Formats a Temporal object or Date into an array of parts */

22

formatToParts(date: TemporalFormattable | Date): Intl.DateTimeFormatPart[];

23

24

/** Formats a range between two Temporal objects */

25

formatRange(startDate: TemporalFormattable, endDate: TemporalFormattable): string;

26

27

/** Formats a range between two Temporal objects into an array of parts */

28

formatRangeToParts(startDate: TemporalFormattable, endDate: TemporalFormattable): Intl.DateTimeFormatPart[];

29

30

/** Returns the supported locales */

31

static supportedLocalesOf(locales: LocalesArgument, options?: Intl.SupportedLocalesOptions): string[];

32

}

33

```

34

35

### Supported Temporal Types

36

37

The enhanced DateTimeFormat supports all major Temporal types for formatting.

38

39

```typescript { .api }

40

/**

41

* Union type of all Temporal objects that can be formatted

42

*/

43

type TemporalFormattable =

44

| Instant

45

| ZonedDateTime

46

| PlainDateTime

47

| PlainDate

48

| PlainTime

49

| PlainYearMonth

50

| PlainMonthDay;

51

52

type LocalesArgument = string | string[] | undefined;

53

```

54

55

### Formatting Individual Temporal Types

56

57

Format specific Temporal types with locale-appropriate output.

58

59

**Usage Examples:**

60

61

```typescript

62

import { Temporal, Intl } from "temporal-polyfill";

63

64

// Create formatter instances

65

const dateFormatter = new Intl.DateTimeFormat('en-US', {

66

year: 'numeric',

67

month: 'long',

68

day: 'numeric'

69

});

70

71

const timeFormatter = new Intl.DateTimeFormat('en-US', {

72

hour: 'numeric',

73

minute: '2-digit',

74

second: '2-digit',

75

timeZoneName: 'short'

76

});

77

78

const dateTimeFormatter = new Intl.DateTimeFormat('en-US', {

79

weekday: 'long',

80

year: 'numeric',

81

month: 'long',

82

day: 'numeric',

83

hour: 'numeric',

84

minute: '2-digit',

85

timeZone: 'America/New_York'

86

});

87

88

// Format PlainDate

89

const plainDate = Temporal.PlainDate.from('2024-03-15');

90

console.log(dateFormatter.format(plainDate)); // "March 15, 2024"

91

92

// Format PlainTime

93

const plainTime = Temporal.PlainTime.from('14:30:00');

94

console.log(timeFormatter.format(plainTime)); // "2:30:00 PM GMT"

95

96

// Format PlainDateTime

97

const plainDateTime = Temporal.PlainDateTime.from('2024-03-15T14:30:00');

98

console.log(dateTimeFormatter.format(plainDateTime)); // "Friday, March 15, 2024 at 2:30 PM EST"

99

100

// Format ZonedDateTime

101

const zonedDateTime = Temporal.ZonedDateTime.from('2024-03-15T14:30:00[America/New_York]');

102

console.log(dateTimeFormatter.format(zonedDateTime)); // "Friday, March 15, 2024 at 2:30 PM EDT"

103

104

// Format Instant

105

const instant = Temporal.Now.instant();

106

console.log(dateTimeFormatter.format(instant)); // Current time in New York timezone

107

108

// Format PlainYearMonth

109

const yearMonthFormatter = new Intl.DateTimeFormat('en-US', {

110

year: 'numeric',

111

month: 'long'

112

});

113

const yearMonth = Temporal.PlainYearMonth.from('2024-03');

114

console.log(yearMonthFormatter.format(yearMonth)); // "March 2024"

115

116

// Format PlainMonthDay

117

const monthDayFormatter = new Intl.DateTimeFormat('en-US', {

118

month: 'long',

119

day: 'numeric'

120

});

121

const monthDay = Temporal.PlainMonthDay.from('03-15');

122

console.log(monthDayFormatter.format(monthDay)); // "March 15"

123

```

124

125

### Localized Formatting

126

127

Format Temporal objects in different locales with appropriate cultural conventions.

128

129

**Usage Examples:**

130

131

```typescript

132

import { Temporal, Intl } from "temporal-polyfill";

133

134

const dateTime = Temporal.ZonedDateTime.from('2024-03-15T14:30:00[Europe/Paris]');

135

136

// Different locales

137

const locales = ['en-US', 'fr-FR', 'de-DE', 'ja-JP', 'ar-SA'];

138

139

const formatters = locales.map(locale => ({

140

locale,

141

formatter: new Intl.DateTimeFormat(locale, {

142

weekday: 'long',

143

year: 'numeric',

144

month: 'long',

145

day: 'numeric',

146

hour: 'numeric',

147

minute: '2-digit',

148

timeZoneName: 'short'

149

})

150

}));

151

152

formatters.forEach(({ locale, formatter }) => {

153

console.log(`${locale}: ${formatter.format(dateTime)}`);

154

});

155

156

// Output examples:

157

// en-US: Friday, March 15, 2024 at 2:30 PM CET

158

// fr-FR: vendredi 15 mars 2024 à 14:30 CET

159

// de-DE: Freitag, 15. März 2024 um 14:30 CET

160

// ja-JP: 2024年3月15日金曜日 14:30 CET

161

// ar-SA: الجمعة، ١٥ مارس ٢٠٢٤ في ٢:٣٠ م CET

162

163

// Currency and number formatting in dates

164

const businessFormatter = new Intl.DateTimeFormat('en-US', {

165

month: 'short',

166

day: 'numeric',

167

year: 'numeric',

168

hour: 'numeric',

169

minute: '2-digit',

170

timeZone: 'America/New_York'

171

});

172

173

const businessDate = Temporal.ZonedDateTime.from('2024-03-15T16:30:00[America/New_York]');

174

console.log(`Report generated: ${businessFormatter.format(businessDate)}`);

175

// "Report generated: Mar 15, 2024 at 4:30 PM"

176

```

177

178

### Format to Parts

179

180

Get detailed formatting parts for custom display and analysis.

181

182

**Usage Examples:**

183

184

```typescript

185

import { Temporal, Intl } from "temporal-polyfill";

186

187

const dateTime = Temporal.ZonedDateTime.from('2024-03-15T14:30:00[America/New_York]');

188

189

const formatter = new Intl.DateTimeFormat('en-US', {

190

weekday: 'long',

191

year: 'numeric',

192

month: 'long',

193

day: 'numeric',

194

hour: 'numeric',

195

minute: '2-digit',

196

timeZoneName: 'short'

197

});

198

199

const parts = formatter.formatToParts(dateTime);

200

console.log(parts);

201

202

// Example output:

203

// [

204

// { type: 'weekday', value: 'Friday' },

205

// { type: 'literal', value: ', ' },

206

// { type: 'month', value: 'March' },

207

// { type: 'literal', value: ' ' },

208

// { type: 'day', value: '15' },

209

// { type: 'literal', value: ', ' },

210

// { type: 'year', value: '2024' },

211

// { type: 'literal', value: ' at ' },

212

// { type: 'hour', value: '2' },

213

// { type: 'literal', value: ':' },

214

// { type: 'minute', value: '30' },

215

// { type: 'literal', value: ' ' },

216

// { type: 'dayPeriod', value: 'PM' },

217

// { type: 'literal', value: ' ' },

218

// { type: 'timeZoneName', value: 'EDT' }

219

// ]

220

221

// Use parts for custom formatting

222

function formatWithHighlight(temporal: TemporalFormattable): string {

223

const parts = formatter.formatToParts(temporal);

224

return parts

225

.map(part => {

226

if (part.type === 'weekday' || part.type === 'month') {

227

return `<strong>${part.value}</strong>`;

228

}

229

return part.value;

230

})

231

.join('');

232

}

233

234

console.log(formatWithHighlight(dateTime));

235

// "<strong>Friday</strong>, <strong>March</strong> 15, 2024 at 2:30 PM EDT"

236

```

237

238

### Range Formatting

239

240

Format ranges between two Temporal objects with intelligent range handling.

241

242

**Usage Examples:**

243

244

```typescript

245

import { Temporal, Intl } from "temporal-polyfill";

246

247

const rangeFormatter = new Intl.DateTimeFormat('en-US', {

248

year: 'numeric',

249

month: 'short',

250

day: 'numeric',

251

hour: 'numeric',

252

minute: '2-digit',

253

timeZone: 'America/New_York'

254

});

255

256

// Date range (same day)

257

const startTime = Temporal.ZonedDateTime.from('2024-03-15T14:30:00[America/New_York]');

258

const endTime = Temporal.ZonedDateTime.from('2024-03-15T16:00:00[America/New_York]');

259

260

console.log(rangeFormatter.formatRange(startTime, endTime));

261

// "Mar 15, 2024, 2:30 PM – 4:00 PM"

262

263

// Date range (different days)

264

const startDate = Temporal.PlainDate.from('2024-03-15');

265

const endDate = Temporal.PlainDate.from('2024-03-17');

266

267

const dateRangeFormatter = new Intl.DateTimeFormat('en-US', {

268

year: 'numeric',

269

month: 'short',

270

day: 'numeric'

271

});

272

273

console.log(dateRangeFormatter.formatRange(startDate, endDate));

274

// "Mar 15 – 17, 2024"

275

276

// Month range

277

const startMonth = Temporal.PlainYearMonth.from('2024-01');

278

const endMonth = Temporal.PlainYearMonth.from('2024-03');

279

280

const monthRangeFormatter = new Intl.DateTimeFormat('en-US', {

281

year: 'numeric',

282

month: 'long'

283

});

284

285

console.log(monthRangeFormatter.formatRange(startMonth, endMonth));

286

// "January – March 2024"

287

288

// Range parts for custom formatting

289

const rangeParts = rangeFormatter.formatRangeToParts(startTime, endTime);

290

console.log(rangeParts);

291

292

// Example output:

293

// [

294

// { type: 'month', value: 'Mar', source: 'startRange' },

295

// { type: 'literal', value: ' ', source: 'startRange' },

296

// { type: 'day', value: '15', source: 'startRange' },

297

// { type: 'literal', value: ', ', source: 'startRange' },

298

// { type: 'year', value: '2024', source: 'startRange' },

299

// { type: 'literal', value: ', ', source: 'startRange' },

300

// { type: 'hour', value: '2', source: 'startRange' },

301

// { type: 'literal', value: ':', source: 'startRange' },

302

// { type: 'minute', value: '30', source: 'startRange' },

303

// { type: 'literal', value: ' ', source: 'startRange' },

304

// { type: 'dayPeriod', value: 'PM', source: 'startRange' },

305

// { type: 'literal', value: ' – ', source: 'shared' },

306

// { type: 'hour', value: '4', source: 'endRange' },

307

// { type: 'literal', value: ':', source: 'endRange' },

308

// { type: 'minute', value: '00', source: 'endRange' },

309

// { type: 'literal', value: ' ', source: 'endRange' },

310

// { type: 'dayPeriod', value: 'PM', source: 'endRange' }

311

// ]

312

```

313

314

### Business Applications

315

316

Common patterns for using Intl formatting in business applications.

317

318

**Usage Examples:**

319

320

```typescript

321

import { Temporal, Intl } from "temporal-polyfill";

322

323

// Meeting scheduler with international support

324

class MeetingScheduler {

325

private readonly formatter: Intl.DateTimeFormat;

326

327

constructor(locale: string, timeZone: string) {

328

this.formatter = new Intl.DateTimeFormat(locale, {

329

weekday: 'long',

330

year: 'numeric',

331

month: 'long',

332

day: 'numeric',

333

hour: 'numeric',

334

minute: '2-digit',

335

timeZone

336

});

337

}

338

339

formatMeeting(

340

startTime: Temporal.ZonedDateTime,

341

duration: Temporal.Duration

342

): string {

343

const endTime = startTime.add(duration);

344

return this.formatter.formatRange(startTime, endTime);

345

}

346

347

formatMeetingInvite(

348

startTime: Temporal.ZonedDateTime,

349

duration: Temporal.Duration,

350

attendeeTimeZones: string[]

351

): string[] {

352

return attendeeTimeZones.map(tz => {

353

const localStart = startTime.withTimeZone(tz);

354

const localEnd = localStart.add(duration);

355

const localFormatter = new Intl.DateTimeFormat(undefined, {

356

weekday: 'long',

357

year: 'numeric',

358

month: 'long',

359

day: 'numeric',

360

hour: 'numeric',

361

minute: '2-digit',

362

timeZone: tz,

363

timeZoneName: 'short'

364

});

365

return localFormatter.formatRange(localStart, localEnd);

366

});

367

}

368

}

369

370

// Report generation with localization

371

class ReportGenerator {

372

generateTimeStampedReport(

373

data: any,

374

locale: string = 'en-US',

375

timeZone: string = Temporal.Now.timeZoneId()

376

): object {

377

const now = Temporal.Now.zonedDateTimeISO(timeZone);

378

const formatter = new Intl.DateTimeFormat(locale, {

379

year: 'numeric',

380

month: 'long',

381

day: 'numeric',

382

hour: 'numeric',

383

minute: '2-digit',

384

second: '2-digit',

385

timeZoneName: 'short'

386

});

387

388

return {

389

generatedAt: formatter.format(now),

390

timeZone,

391

locale,

392

data

393

};

394

}

395

396

formatDateRange(

397

startDate: Temporal.PlainDate,

398

endDate: Temporal.PlainDate,

399

locale: string = 'en-US'

400

): string {

401

const formatter = new Intl.DateTimeFormat(locale, {

402

year: 'numeric',

403

month: 'short',

404

day: 'numeric'

405

});

406

return formatter.formatRange(startDate, endDate);

407

}

408

}

409

410

// Event calendar with multiple time zones

411

class EventCalendar {

412

formatEventForTimezone(

413

event: {

414

start: Temporal.ZonedDateTime,

415

end: Temporal.ZonedDateTime,

416

title: string

417

},

418

targetTimeZone: string,

419

locale: string = 'en-US'

420

): string {

421

const localStart = event.start.withTimeZone(targetTimeZone);

422

const localEnd = event.end.withTimeZone(targetTimeZone);

423

424

const formatter = new Intl.DateTimeFormat(locale, {

425

month: 'short',

426

day: 'numeric',

427

hour: 'numeric',

428

minute: '2-digit',

429

timeZone: targetTimeZone,

430

timeZoneName: 'short'

431

});

432

433

const timeRange = formatter.formatRange(localStart, localEnd);

434

return `${event.title}: ${timeRange}`;

435

}

436

}

437

```

438

439

## Types

440

441

```typescript { .api }

442

// Type definitions for international formatting

443

type TemporalFormattable =

444

| Instant

445

| ZonedDateTime

446

| PlainDateTime

447

| PlainDate

448

| PlainTime

449

| PlainYearMonth

450

| PlainMonthDay;

451

452

type LocalesArgument = string | string[] | undefined;

453

454

// Enhanced DateTimeFormat interface

455

interface DateTimeFormat extends Intl.DateTimeFormat {

456

format(date: TemporalFormattable | Date): string;

457

formatToParts(date: TemporalFormattable | Date): Intl.DateTimeFormatPart[];

458

formatRange(startDate: TemporalFormattable, endDate: TemporalFormattable): string;

459

formatRangeToParts(startDate: TemporalFormattable, endDate: TemporalFormattable): Intl.DateTimeFormatPart[];

460

}

461

462

// Standard Intl.DateTimeFormatPart with range source information

463

interface DateTimeFormatPart extends Intl.DateTimeFormatPart {

464

source?: 'startRange' | 'endRange' | 'shared';

465

}

466

467

// Standard Intl.DateTimeFormatOptions (extended for Temporal)

468

interface DateTimeFormatOptions extends Intl.DateTimeFormatOptions {

469

// All standard Intl.DateTimeFormatOptions are supported

470

// when formatting Temporal objects

471

}

472

473

// Extended Intl namespace

474

interface IntlExtended extends Intl {

475

DateTimeFormat: DateTimeFormat;

476

}

477

478

// Common format part types

479

type FormatPartType =

480

| 'era'

481

| 'year'

482

| 'month'

483

| 'day'

484

| 'weekday'

485

| 'hour'

486

| 'minute'

487

| 'second'

488

| 'timeZoneName'

489

| 'dayPeriod'

490

| 'literal'

491

| 'fractionalSecond';

492

```