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

calendar-system.mddocs/

0

# Calendar System

1

2

Specialized classes for working with calendar-specific date components like year-month and month-day combinations. These classes handle partial date representations and calendar-aware operations.

3

4

## Capabilities

5

6

### PlainYearMonth

7

8

Represents a year and month combination in a calendar system. Ideal for monthly reports, subscription periods, or any year-month specific operations.

9

10

```typescript { .api }

11

/**

12

* Represents a year and month combination in a calendar

13

*/

14

class PlainYearMonth {

15

/** Creates a PlainYearMonth from various inputs */

16

static from(item: PlainYearMonthLike | string, options?: AssignmentOptions): PlainYearMonth;

17

/** Compares two year-months and returns -1, 0, or 1 */

18

static compare(one: PlainYearMonthLike, two: PlainYearMonthLike): ComparisonResult;

19

20

// Year-month component properties

21

readonly calendarId: string;

22

readonly year: number;

23

readonly month: number;

24

readonly monthCode: string;

25

readonly era: string | undefined;

26

readonly eraYear: number | undefined;

27

28

// Calendar-computed properties

29

readonly daysInMonth: number;

30

readonly daysInYear: number;

31

readonly monthsInYear: number;

32

readonly inLeapYear: boolean;

33

34

// Year-month manipulation methods

35

/** Returns a new PlainYearMonth with the duration added */

36

add(duration: DurationLike, options?: ArithmeticOptions): PlainYearMonth;

37

/** Returns a new PlainYearMonth with the duration subtracted */

38

subtract(duration: DurationLike, options?: ArithmeticOptions): PlainYearMonth;

39

/** Returns a new PlainYearMonth with the specified fields changed */

40

with(yearMonthLike: PlainYearMonthLike, options?: AssignmentOptions): PlainYearMonth;

41

42

// Comparison and difference methods

43

/** Returns the duration from this year-month until the other year-month */

44

until(other: PlainYearMonthLike, options?: DifferenceOptions<YearMonthUnit>): Duration;

45

/** Returns the duration from the other year-month since this year-month */

46

since(other: PlainYearMonthLike, options?: DifferenceOptions<YearMonthUnit>): Duration;

47

/** Tests if this year-month equals another year-month */

48

equals(other: PlainYearMonthLike): boolean;

49

50

// Conversion methods

51

/** Combines this year-month with a day to create a PlainDate */

52

toPlainDate(day: PlainDateLike): PlainDate;

53

54

// String representation methods

55

/** Returns a locale-formatted string representation */

56

toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;

57

/** Returns an ISO 8601 string representation */

58

toString(options?: ShowCalendarOption): string;

59

/** Returns a JSON representation (same as toString) */

60

toJSON(): string;

61

/** Throws a TypeError when used in comparison operators */

62

valueOf(): never;

63

}

64

```

65

66

**Usage Examples:**

67

68

```typescript

69

import { Temporal } from "temporal-polyfill";

70

71

// Creating year-months

72

const currentMonth = Temporal.Now.plainDateISO().toPlainYearMonth();

73

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

74

const fromObject = Temporal.PlainYearMonth.from({ year: 2024, month: 3 });

75

76

// Monthly operations

77

const nextMonth = currentMonth.add({ months: 1 });

78

const lastYear = currentMonth.subtract({ years: 1 });

79

const sameMonthNextYear = currentMonth.with({ year: currentMonth.year + 1 });

80

81

// Calendar information

82

console.log(currentMonth.daysInMonth); // e.g., 31 for March

83

console.log(currentMonth.inLeapYear); // true/false

84

console.log(currentMonth.monthsInYear); // 12 for Gregorian calendar

85

86

// Creating full dates from year-month

87

const firstOfMonth = currentMonth.toPlainDate({ day: 1 });

88

const lastOfMonth = currentMonth.toPlainDate({ day: currentMonth.daysInMonth });

89

90

// Monthly comparisons

91

const monthsBetween = fromString.until(nextMonth, { largestUnit: 'month' });

92

const isEarlier = Temporal.PlainYearMonth.compare(fromString, nextMonth) < 0;

93

94

// Business use cases

95

function getQuarterStart(yearMonth: Temporal.PlainYearMonth): Temporal.PlainYearMonth {

96

const quarterMonth = Math.floor((yearMonth.month - 1) / 3) * 3 + 1;

97

return yearMonth.with({ month: quarterMonth });

98

}

99

100

function getMonthlyReport(yearMonth: Temporal.PlainYearMonth) {

101

const startOfMonth = yearMonth.toPlainDate({ day: 1 });

102

const endOfMonth = yearMonth.toPlainDate({ day: yearMonth.daysInMonth });

103

return { startOfMonth, endOfMonth, daysInMonth: yearMonth.daysInMonth };

104

}

105

```

106

107

### PlainMonthDay

108

109

Represents a month and day combination in a calendar system. Perfect for recurring events like birthdays, anniversaries, or holidays.

110

111

```typescript { .api }

112

/**

113

* Represents a month and day combination in a calendar

114

*/

115

class PlainMonthDay {

116

/** Creates a PlainMonthDay from various inputs */

117

static from(item: PlainMonthDayLike | string, options?: AssignmentOptions): PlainMonthDay;

118

119

// Month-day component properties

120

readonly calendarId: string;

121

readonly monthCode: string;

122

readonly day: number;

123

124

// Month-day manipulation methods

125

/** Returns a new PlainMonthDay with the specified fields changed */

126

with(monthDayLike: PlainMonthDayLike, options?: AssignmentOptions): PlainMonthDay;

127

128

// Comparison methods

129

/** Tests if this month-day equals another month-day */

130

equals(other: PlainMonthDayLike): boolean;

131

132

// Conversion methods

133

/** Combines this month-day with a year to create a PlainDate */

134

toPlainDate(year: PlainYearMonthLike): PlainDate;

135

136

// String representation methods

137

/** Returns a locale-formatted string representation */

138

toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;

139

/** Returns an ISO 8601 string representation */

140

toString(options?: ShowCalendarOption): string;

141

/** Returns a JSON representation (same as toString) */

142

toJSON(): string;

143

/** Throws a TypeError when used in comparison operators */

144

valueOf(): never;

145

}

146

```

147

148

**Usage Examples:**

149

150

```typescript

151

import { Temporal } from "temporal-polyfill";

152

153

// Creating month-days

154

const birthday = Temporal.PlainMonthDay.from('06-15'); // June 15

155

const fromObject = Temporal.PlainMonthDay.from({ month: 12, day: 25 }); // Christmas

156

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

157

158

// Creating specific year dates from month-day

159

const thisYear = birthday.toPlainDate({ year: 2024 });

160

const nextYear = birthday.toPlainDate({ year: 2025 });

161

162

// Holiday and recurring event handling

163

const holidays = [

164

Temporal.PlainMonthDay.from('01-01'), // New Year's Day

165

Temporal.PlainMonthDay.from('07-04'), // Independence Day

166

Temporal.PlainMonthDay.from('12-25'), // Christmas

167

];

168

169

function getHolidaysForYear(year: number): Temporal.PlainDate[] {

170

return holidays.map(holiday => holiday.toPlainDate({ year }));

171

}

172

173

function isHoliday(date: Temporal.PlainDate): boolean {

174

const monthDay = date.toPlainMonthDay();

175

return holidays.some(holiday => holiday.equals(monthDay));

176

}

177

178

// Age calculation on birthday

179

function getNextBirthday(

180

birthday: Temporal.PlainMonthDay,

181

referenceDate: Temporal.PlainDate = Temporal.Now.plainDateISO()

182

): Temporal.PlainDate {

183

let birthdayThisYear = birthday.toPlainDate({ year: referenceDate.year });

184

185

if (Temporal.PlainDate.compare(birthdayThisYear, referenceDate) < 0) {

186

// Birthday already passed this year, get next year's

187

birthdayThisYear = birthday.toPlainDate({ year: referenceDate.year + 1 });

188

}

189

190

return birthdayThisYear;

191

}

192

193

// Leap year handling

194

const feb29 = Temporal.PlainMonthDay.from('02-29');

195

196

function getLeapDayForYear(year: number): Temporal.PlainDate | null {

197

try {

198

return feb29.toPlainDate({ year });

199

} catch {

200

return null; // Not a leap year

201

}

202

}

203

204

// Subscription management

205

class RecurringEvent {

206

constructor(

207

public readonly monthDay: Temporal.PlainMonthDay,

208

public readonly description: string

209

) {}

210

211

getNextOccurrence(after: Temporal.PlainDate = Temporal.Now.plainDateISO()): Temporal.PlainDate {

212

let occurrence = this.monthDay.toPlainDate({ year: after.year });

213

214

if (Temporal.PlainDate.compare(occurrence, after) <= 0) {

215

occurrence = this.monthDay.toPlainDate({ year: after.year + 1 });

216

}

217

218

return occurrence;

219

}

220

221

getOccurrenceInYear(year: number): Temporal.PlainDate {

222

return this.monthDay.toPlainDate({ year });

223

}

224

}

225

226

const anniversary = new RecurringEvent(

227

Temporal.PlainMonthDay.from('06-01'),

228

'Company Anniversary'

229

);

230

```

231

232

### Calendar-Aware Operations

233

234

Working with different calendar systems and handling calendar-specific behavior.

235

236

```typescript { .api }

237

// Calendar interface (for reference)

238

interface Calendar {

239

readonly id: string;

240

dateFromFields(fields: DateLike, options?: AssignmentOptions): PlainDate;

241

yearMonthFromFields(fields: YearMonthLike, options?: AssignmentOptions): PlainYearMonth;

242

monthDayFromFields(fields: MonthDayLike, options?: AssignmentOptions): PlainMonthDay;

243

dateAdd(date: PlainDate, duration: Duration, options?: ArithmeticOptions): PlainDate;

244

dateUntil(one: PlainDate, two: PlainDate, options?: DifferenceOptions): Duration;

245

year(date: PlainDate): number;

246

month(date: PlainDate): number;

247

monthCode(date: PlainDate): string;

248

day(date: PlainDate): number;

249

era(date: PlainDate): string | undefined;

250

eraYear(date: PlainDate): number | undefined;

251

dayOfWeek(date: PlainDate): number;

252

dayOfYear(date: PlainDate): number;

253

weekOfYear(date: PlainDate): number;

254

daysInWeek(date: PlainDate): number;

255

daysInMonth(date: PlainDate): number;

256

daysInYear(date: PlainDate): number;

257

monthsInYear(date: PlainDate): number;

258

inLeapYear(date: PlainDate): boolean;

259

toString(): string;

260

toJSON(): string;

261

}

262

```

263

264

**Usage Examples:**

265

266

```typescript

267

import { Temporal } from "temporal-polyfill";

268

269

// Working with different calendars (theoretical - actual calendar support varies)

270

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

271

const isoYearMonth = gregorianYM.withCalendar('iso8601');

272

273

// Month code handling (important for non-Gregorian calendars)

274

const marchMD = Temporal.PlainMonthDay.from({ monthCode: 'M03', day: 15 });

275

console.log(marchMD.monthCode); // 'M03'

276

277

// Era-aware operations (for calendars with eras)

278

const historicalYM = Temporal.PlainYearMonth.from({

279

era: 'ce',

280

eraYear: 2024,

281

month: 3

282

});

283

284

// Calendar property access

285

function getCalendarInfo(yearMonth: Temporal.PlainYearMonth): object {

286

return {

287

calendar: yearMonth.calendarId,

288

year: yearMonth.year,

289

month: yearMonth.month,

290

monthCode: yearMonth.monthCode,

291

era: yearMonth.era,

292

eraYear: yearMonth.eraYear,

293

daysInMonth: yearMonth.daysInMonth,

294

daysInYear: yearMonth.daysInYear,

295

monthsInYear: yearMonth.monthsInYear,

296

inLeapYear: yearMonth.inLeapYear

297

};

298

}

299

```

300

301

## Types

302

303

```typescript { .api }

304

// Core type definitions for calendar system classes

305

type PlainYearMonthLike = PlainYearMonth | PlainYearMonthFields | string;

306

type PlainMonthDayLike = PlainMonthDay | PlainMonthDayFields | string;

307

type CalendarLike = string | Calendar;

308

309

interface PlainYearMonthFields {

310

era?: string;

311

eraYear?: number;

312

year: number;

313

month?: number;

314

monthCode?: string;

315

calendar?: CalendarLike;

316

}

317

318

interface PlainMonthDayFields {

319

monthCode?: string;

320

month?: number;

321

day: number;

322

calendar?: CalendarLike;

323

}

324

325

// Unit types for year-month operations

326

type YearMonthUnit = 'year' | 'month';

327

328

// Options for calendar system operations

329

interface ShowCalendarOption {

330

calendarName?: 'auto' | 'always' | 'never' | 'critical';

331

}

332

333

interface AssignmentOptions {

334

overflow?: OverflowMode;

335

}

336

337

interface ArithmeticOptions {

338

overflow?: OverflowMode;

339

}

340

341

interface DifferenceOptions<T extends string> {

342

largestUnit?: T;

343

smallestUnit?: T;

344

roundingIncrement?: number;

345

roundingMode?: RoundingMode;

346

}

347

348

// Common types

349

type OverflowMode = 'constrain' | 'reject';

350

type RoundingMode = 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';

351

type ComparisonResult = -1 | 0 | 1;

352

353

// Date-like interface for toPlainDate operations

354

interface DateLike {

355

era?: string;

356

eraYear?: number;

357

year?: number;

358

month?: number;

359

monthCode?: string;

360

day?: number;

361

calendar?: CalendarLike;

362

}

363

364

interface YearMonthLike {

365

era?: string;

366

eraYear?: number;

367

year?: number;

368

month?: number;

369

monthCode?: string;

370

calendar?: CalendarLike;

371

}

372

373

interface MonthDayLike {

374

monthCode?: string;

375

month?: number;

376

day?: number;

377

calendar?: CalendarLike;

378

}

379

```