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

duration-arithmetic.mddocs/

0

# Duration and Arithmetic

1

2

Duration class for representing time spans and performing date arithmetic operations. Durations can represent time periods from nanoseconds to years and are essential for all temporal calculations.

3

4

## Capabilities

5

6

### Duration

7

8

Represents a duration of time with support for all time units from nanoseconds to years. Handles both positive and negative durations with precise arithmetic operations.

9

10

```typescript { .api }

11

/**

12

* Represents a duration of time (time span)

13

*/

14

class Duration {

15

/** Creates a Duration from various inputs */

16

static from(item: DurationLike | string): Duration;

17

/** Compares two durations and returns -1, 0, or 1 */

18

static compare(one: DurationLike, two: DurationLike, options?: DurationArithmeticOptions): ComparisonResult;

19

/** Constructs a new Duration with specified components */

20

constructor(years?: number, months?: number, weeks?: number, days?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number, microseconds?: number, nanoseconds?: number);

21

22

// Duration component properties

23

readonly years: number;

24

readonly months: number;

25

readonly weeks: number;

26

readonly days: number;

27

readonly hours: number;

28

readonly minutes: number;

29

readonly seconds: number;

30

readonly milliseconds: number;

31

readonly microseconds: number;

32

readonly nanoseconds: number;

33

34

// Computed properties

35

readonly sign: -1 | 0 | 1; // Sign of the duration

36

readonly blank: boolean; // True if duration is zero

37

38

// Duration manipulation methods

39

/** Returns a new Duration with the specified components changed */

40

with(durationLike: DurationLike): Duration;

41

/** Returns a new Duration with opposite sign */

42

negated(): Duration;

43

/** Returns a new Duration with absolute (positive) values */

44

abs(): Duration;

45

/** Returns a new Duration with the other duration added */

46

add(other: DurationLike, options?: DurationArithmeticOptions): Duration;

47

/** Returns a new Duration with the other duration subtracted */

48

subtract(other: DurationLike, options?: DurationArithmeticOptions): Duration;

49

50

// Precision and conversion methods

51

/** Rounds this duration to the specified unit or precision */

52

round(roundTo: DurationUnit | DurationRoundingOptions): Duration;

53

/** Returns the total duration in the specified unit as a number */

54

total(totalOf: DurationUnit | DurationTotalOfOptions): number;

55

56

// String representation methods

57

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

58

toLocaleString(locales?: string | string[], options?: any): string;

59

/** Returns an ISO 8601 duration string representation */

60

toString(options?: DurationToStringOptions): string;

61

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

62

toJSON(): string;

63

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

64

valueOf(): never;

65

}

66

```

67

68

**Usage Examples:**

69

70

```typescript

71

import { Temporal } from "temporal-polyfill";

72

73

// Creating durations

74

const twoHours = Temporal.Duration.from({ hours: 2 });

75

const fromString = Temporal.Duration.from('PT2H30M'); // 2 hours 30 minutes

76

const constructed = new Temporal.Duration(0, 0, 0, 0, 2, 30, 0); // 2 hours 30 minutes

77

const complex = Temporal.Duration.from({

78

years: 1,

79

months: 2,

80

days: 10,

81

hours: 8,

82

minutes: 30

83

});

84

85

// Duration arithmetic

86

const longer = twoHours.add({ minutes: 30 });

87

const shorter = twoHours.subtract({ minutes: 15 });

88

const combined = twoHours.add(Temporal.Duration.from('PT30M'));

89

90

// Duration properties

91

console.log(twoHours.hours); // 2

92

console.log(twoHours.minutes); // 0

93

console.log(twoHours.sign); // 1 (positive)

94

console.log(twoHours.blank); // false

95

96

// Negative durations

97

const backwards = twoHours.negated();

98

console.log(backwards.sign); // -1 (negative)

99

const positive = backwards.abs();

100

101

// Converting to totals

102

const totalMinutes = twoHours.total('minutes'); // 120

103

const totalSeconds = twoHours.total('seconds'); // 7200

104

const totalDays = complex.total({ unit: 'days', relativeTo: '2024-01-01' });

105

106

// Rounding durations

107

const precise = Temporal.Duration.from('PT2H23M47.123S');

108

const roundedToMinute = precise.round('minute');

109

const roundedUp = precise.round({ smallestUnit: 'minute', roundingMode: 'ceil' });

110

111

// Duration comparisons

112

const first = Temporal.Duration.from('PT2H');

113

const second = Temporal.Duration.from('PT90M'); // 1.5 hours

114

const comparison = Temporal.Duration.compare(first, second); // 1 (first > second)

115

116

// Using durations with dates

117

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

118

const futureDate = startDate.add(complex);

119

const duration = startDate.until(futureDate);

120

```

121

122

### Calendar-Relative Arithmetic

123

124

Durations can be calendar-relative, meaning operations like adding months or years depend on the calendar system and starting date.

125

126

```typescript { .api }

127

// Calendar-relative duration operations

128

interface DurationArithmeticOptions {

129

relativeTo?: PlainDateLike | ZonedDateTimeLike | string;

130

}

131

132

interface DurationTotalOfOptions {

133

unit: DurationUnit;

134

relativeTo?: PlainDateLike | ZonedDateTimeLike | string;

135

}

136

```

137

138

**Usage Examples:**

139

140

```typescript

141

import { Temporal } from "temporal-polyfill";

142

143

// Calendar-aware arithmetic

144

const oneMonth = Temporal.Duration.from({ months: 1 });

145

const jan31 = Temporal.PlainDate.from('2024-01-31');

146

147

// Adding 1 month to Jan 31 gives Feb 29 (2024 is leap year)

148

const feb29 = jan31.add(oneMonth);

149

150

// Duration calculations with relative anchor

151

const duration1 = Temporal.Duration.from({ months: 2, days: 10 });

152

const duration2 = Temporal.Duration.from({ days: 70 });

153

154

// Compare relative to a specific date

155

const comparison = Temporal.Duration.compare(

156

duration1,

157

duration2,

158

{ relativeTo: '2024-01-01' }

159

);

160

161

// Convert to total days relative to start date

162

const totalDays = duration1.total({

163

unit: 'days',

164

relativeTo: '2024-01-01'

165

}); // Takes into account actual month lengths

166

167

// Timezone-aware duration arithmetic

168

const zonedStart = Temporal.ZonedDateTime.from('2024-03-10T01:00:00[America/New_York]');

169

const dstDuration = Temporal.Duration.from({ hours: 3 });

170

171

// Handles DST transition - spring forward skips hour

172

const zonedEnd = zonedStart.add(dstDuration);

173

console.log(zonedStart.until(zonedEnd, { smallestUnit: 'hour' })); // PT3H

174

```

175

176

### Duration Balancing and Normalization

177

178

Durations can be balanced and normalized to different unit combinations.

179

180

```typescript { .api }

181

interface DurationRoundingOptions {

182

largestUnit?: DurationUnit;

183

smallestUnit: DurationUnit;

184

roundingIncrement?: number;

185

roundingMode?: RoundingMode;

186

relativeTo?: PlainDateLike | ZonedDateTimeLike | string;

187

}

188

```

189

190

**Usage Examples:**

191

192

```typescript

193

import { Temporal } from "temporal-polyfill";

194

195

// Duration balancing

196

const unbalanced = Temporal.Duration.from({

197

hours: 25,

198

minutes: 90,

199

seconds: 120

200

});

201

202

// Balance to show days and hours

203

const balanced = unbalanced.round({

204

largestUnit: 'day',

205

smallestUnit: 'minute'

206

});

207

console.log(balanced.toString()); // P1DT3H32M

208

209

// Fine-tune precision

210

const precise = Temporal.Duration.from('PT2H23M47.123456789S');

211

const toMillis = precise.round({

212

smallestUnit: 'millisecond',

213

roundingMode: 'halfExpand'

214

});

215

216

// Round to specific increments

217

const rounded15Min = precise.round({

218

smallestUnit: 'minute',

219

roundingIncrement: 15,

220

roundingMode: 'halfExpand'

221

});

222

223

// Balance relative to a date (for calendar units)

224

const mixed = Temporal.Duration.from({ days: 40, hours: 30 });

225

const balanced2 = mixed.round({

226

largestUnit: 'month',

227

smallestUnit: 'day',

228

relativeTo: '2024-01-01'

229

}); // Converts days to months based on actual month lengths

230

```

231

232

### Working with Business Logic

233

234

Common patterns for using durations in business applications.

235

236

**Usage Examples:**

237

238

```typescript

239

import { Temporal } from "temporal-polyfill";

240

241

// Meeting scheduling

242

function scheduleMeeting(

243

startTime: Temporal.ZonedDateTime,

244

duration: Temporal.Duration

245

): Temporal.ZonedDateTime {

246

return startTime.add(duration);

247

}

248

249

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

250

const meetingDuration = Temporal.Duration.from({ hours: 1, minutes: 30 });

251

const meetingEnd = scheduleMeeting(meetingStart, meetingDuration);

252

253

// Age calculation

254

function calculateAge(

255

birthDate: Temporal.PlainDate,

256

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

257

): Temporal.Duration {

258

return birthDate.until(currentDate, { largestUnit: 'year' });

259

}

260

261

const birthday = Temporal.PlainDate.from('1990-06-15');

262

const age = calculateAge(birthday);

263

console.log(`Age: ${age.years} years, ${age.months} months, ${age.days} days`);

264

265

// Time tracking

266

class TimeTracker {

267

private startTime: Temporal.Instant | null = null;

268

private totalDuration = Temporal.Duration.from({});

269

270

start(): void {

271

this.startTime = Temporal.Now.instant();

272

}

273

274

stop(): Temporal.Duration {

275

if (!this.startTime) {

276

throw new Error('Timer not started');

277

}

278

const elapsed = this.startTime.until(Temporal.Now.instant());

279

this.totalDuration = this.totalDuration.add(elapsed);

280

this.startTime = null;

281

return elapsed;

282

}

283

284

getTotal(): Temporal.Duration {

285

return this.totalDuration;

286

}

287

288

reset(): void {

289

this.totalDuration = Temporal.Duration.from({});

290

this.startTime = null;

291

}

292

}

293

294

// Service level agreement (SLA) calculations

295

function calculateSLAUptime(

296

downtimePeriods: Temporal.Duration[],

297

totalPeriod: Temporal.Duration

298

): number {

299

const totalDowntime = downtimePeriods.reduce(

300

(sum, period) => sum.add(period),

301

Temporal.Duration.from({})

302

);

303

304

const uptime = totalPeriod.subtract(totalDowntime);

305

return uptime.total('seconds') / totalPeriod.total('seconds');

306

}

307

```

308

309

## Types

310

311

```typescript { .api }

312

// Core type definitions for durations

313

type DurationLike = Duration | DurationFields | string;

314

315

interface DurationFields {

316

years?: number;

317

months?: number;

318

weeks?: number;

319

days?: number;

320

hours?: number;

321

minutes?: number;

322

seconds?: number;

323

milliseconds?: number;

324

microseconds?: number;

325

nanoseconds?: number;

326

}

327

328

// Unit types for duration operations

329

type DurationUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond' | 'microsecond' | 'nanosecond';

330

331

// Arithmetic and comparison options

332

interface DurationArithmeticOptions {

333

relativeTo?: PlainDateLike | ZonedDateTimeLike | string;

334

}

335

336

interface DurationRoundingOptions {

337

largestUnit?: DurationUnit;

338

smallestUnit: DurationUnit;

339

roundingIncrement?: number;

340

roundingMode?: RoundingMode;

341

relativeTo?: PlainDateLike | ZonedDateTimeLike | string;

342

}

343

344

interface DurationTotalOfOptions {

345

unit: DurationUnit;

346

relativeTo?: PlainDateLike | ZonedDateTimeLike | string;

347

}

348

349

// String representation options

350

interface DurationToStringOptions {

351

fractionalSecondDigits?: 'auto' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;

352

smallestUnit?: DurationUnit;

353

roundingMode?: RoundingMode;

354

}

355

356

// Common rounding modes

357

type RoundingMode =

358

| 'ceil' // Round up (towards positive infinity)

359

| 'floor' // Round down (towards negative infinity)

360

| 'expand' // Round away from zero

361

| 'trunc' // Round towards zero

362

| 'halfCeil' // Round half up (towards positive infinity)

363

| 'halfFloor' // Round half down (towards negative infinity)

364

| 'halfExpand' // Round half away from zero (default)

365

| 'halfTrunc' // Round half towards zero

366

| 'halfEven'; // Round half to even (banker's rounding)

367

368

// Result type for comparisons

369

type ComparisonResult = -1 | 0 | 1;

370

```