or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-types.mdformatting.mdindex.mdjvm-interop.mdperiods-units.mdserialization.md

periods-units.mddocs/

0

# Periods & Units

1

2

This document covers period representations and arithmetic units for flexible date and time calculations: `DateTimePeriod`, `DatePeriod`, and the `DateTimeUnit` hierarchy.

3

4

## DateTimePeriod

5

6

A period with both date and time components, representing a difference between two instants decomposed into years, months, days, hours, minutes, seconds, and nanoseconds.

7

8

```kotlin { .api }

9

// Constructor

10

data class DateTimePeriod(

11

val years: Int = 0,

12

val months: Int = 0,

13

val days: Int = 0,

14

val hours: Int = 0,

15

val minutes: Int = 0,

16

val seconds: Int = 0,

17

val nanoseconds: Long = 0

18

)

19

20

// Properties

21

val DateTimePeriod.years: Int

22

val DateTimePeriod.months: Int

23

val DateTimePeriod.days: Int

24

val DateTimePeriod.hours: Int

25

val DateTimePeriod.minutes: Int

26

val DateTimePeriod.seconds: Int

27

val DateTimePeriod.nanoseconds: Long

28

29

// Arithmetic operations

30

operator fun DateTimePeriod.plus(other: DateTimePeriod): DateTimePeriod

31

operator fun DateTimePeriod.minus(other: DateTimePeriod): DateTimePeriod

32

operator fun DateTimePeriod.unaryMinus(): DateTimePeriod

33

34

// Companion object functions

35

fun DateTimePeriod.Companion.parse(input: CharSequence): DateTimePeriod

36

37

// String representation (ISO 8601 format)

38

fun DateTimePeriod.toString(): String

39

```

40

41

### Usage Examples

42

43

```kotlin

44

// Create periods

45

val oneYear = DateTimePeriod(years = 1)

46

val twoWeeks = DateTimePeriod(days = 14)

47

val fullPeriod = DateTimePeriod(

48

years = 1,

49

months = 2,

50

days = 15,

51

hours = 3,

52

minutes = 30,

53

seconds = 45

54

)

55

56

// Arithmetic on periods

57

val combined = oneYear + twoWeeks

58

val difference = fullPeriod - oneYear

59

val negated = -fullPeriod

60

61

// Parse ISO 8601 period strings

62

val parsed = DateTimePeriod.parse("P1Y2M15DT3H30M45S")

63

64

// Use with Instant arithmetic (requires timezone)

65

val instant = Clock.System.now()

66

val timeZone = TimeZone.currentSystemDefault()

67

val futureInstant = instant.plus(fullPeriod, timeZone)

68

```

69

70

## DatePeriod

71

72

A period with only date components (years, months, days), representing calendar-based time differences. This is a subtype of `DateTimePeriod` with all time components set to zero.

73

74

```kotlin { .api }

75

// Constructor

76

data class DatePeriod(

77

val years: Int = 0,

78

val months: Int = 0,

79

val days: Int = 0

80

) : DateTimePeriod

81

82

// Properties (inherited from DateTimePeriod)

83

val DatePeriod.years: Int

84

val DatePeriod.months: Int

85

val DatePeriod.days: Int

86

87

// Arithmetic operations (inherited from DateTimePeriod)

88

operator fun DatePeriod.plus(other: DatePeriod): DatePeriod

89

operator fun DatePeriod.minus(other: DatePeriod): DatePeriod

90

operator fun DatePeriod.unaryMinus(): DatePeriod

91

92

// Companion object functions

93

fun DatePeriod.Companion.parse(input: CharSequence): DatePeriod

94

95

// String representation (ISO 8601 format)

96

fun DatePeriod.toString(): String

97

```

98

99

### Usage Examples

100

101

```kotlin

102

// Create date periods

103

val oneYear = DatePeriod(years = 1)

104

val sixMonths = DatePeriod(months = 6)

105

val twoWeeks = DatePeriod(days = 14)

106

107

// Combine periods

108

val quarterAndTwoWeeks = DatePeriod(months = 3, days = 14)

109

val combined = sixMonths + twoWeeks

110

111

// Parse ISO 8601 date period strings

112

val parsed = DatePeriod.parse("P1Y6M14D")

113

114

// Use with LocalDate arithmetic

115

val date = LocalDate(2023, 1, 1)

116

val futureDate = date.plus(quarterAndTwoWeeks)

117

val periodBetween = date.periodUntil(futureDate)

118

```

119

120

## DateTimeUnit

121

122

Sealed class hierarchy representing units for measuring time, providing both duration-based and calendar-based units for datetime arithmetic.

123

124

```kotlin { .api }

125

// Base sealed class

126

sealed class DateTimeUnit {

127

// Duration-based units (independent of calendar/timezone)

128

sealed class TimeBased : DateTimeUnit() {

129

val duration: Duration

130

}

131

132

// Calendar-based units (depend on calendar/timezone)

133

sealed class DateBased : DateTimeUnit()

134

135

// Day-based units (subtype of DateBased)

136

sealed class DayBased : DateBased() {

137

val days: Int

138

}

139

140

// Month-based units (subtype of DateBased)

141

sealed class MonthBased : DateBased() {

142

val months: Int

143

}

144

}

145

```

146

147

### Predefined Units

148

149

```kotlin { .api }

150

// Time-based units (duration-based)

151

val DateTimeUnit.NANOSECOND: DateTimeUnit.TimeBased

152

val DateTimeUnit.MICROSECOND: DateTimeUnit.TimeBased

153

val DateTimeUnit.MILLISECOND: DateTimeUnit.TimeBased

154

val DateTimeUnit.SECOND: DateTimeUnit.TimeBased

155

val DateTimeUnit.MINUTE: DateTimeUnit.TimeBased

156

val DateTimeUnit.HOUR: DateTimeUnit.TimeBased

157

158

// Date-based units (calendar-based)

159

val DateTimeUnit.DAY: DateTimeUnit.DayBased

160

val DateTimeUnit.WEEK: DateTimeUnit.DayBased

161

val DateTimeUnit.MONTH: DateTimeUnit.MonthBased

162

val DateTimeUnit.QUARTER: DateTimeUnit.MonthBased

163

val DateTimeUnit.YEAR: DateTimeUnit.MonthBased

164

```

165

166

### Factory Functions

167

168

```kotlin { .api }

169

// Create custom time-based units

170

fun DateTimeUnit.TimeBased(duration: Duration): DateTimeUnit.TimeBased

171

172

// Create custom day-based units

173

fun DateTimeUnit.DayBased(days: Int): DateTimeUnit.DayBased

174

175

// Create custom month-based units

176

fun DateTimeUnit.MonthBased(months: Int): DateTimeUnit.MonthBased

177

178

// Multiplication operators for creating multiples

179

operator fun DateTimeUnit.times(scalar: Int): DateTimeUnit

180

operator fun Int.times(unit: DateTimeUnit): DateTimeUnit

181

```

182

183

### Usage with Different Types

184

185

#### With Instant (requires TimeZone for DateBased units)

186

187

```kotlin { .api }

188

// TimeBased units - no timezone required

189

fun Instant.plus(value: Int, unit: DateTimeUnit.TimeBased): Instant

190

fun Instant.plus(value: Long, unit: DateTimeUnit.TimeBased): Instant

191

fun Instant.minus(value: Int, unit: DateTimeUnit.TimeBased): Instant

192

fun Instant.minus(value: Long, unit: DateTimeUnit.TimeBased): Instant

193

fun Instant.until(other: Instant, unit: DateTimeUnit.TimeBased): Long

194

195

// DateBased units - timezone required

196

fun Instant.plus(value: Int, unit: DateTimeUnit.DateBased, timeZone: TimeZone): Instant

197

fun Instant.plus(value: Long, unit: DateTimeUnit.DateBased, timeZone: TimeZone): Instant

198

fun Instant.minus(value: Int, unit: DateTimeUnit.DateBased, timeZone: TimeZone): Instant

199

fun Instant.minus(value: Long, unit: DateTimeUnit.DateBased, timeZone: TimeZone): Instant

200

fun Instant.until(other: Instant, unit: DateTimeUnit.DateBased, timeZone: TimeZone): Long

201

```

202

203

#### With LocalDate (only DateBased units)

204

205

```kotlin { .api }

206

fun LocalDate.plus(value: Int, unit: DateTimeUnit.DateBased): LocalDate

207

fun LocalDate.plus(value: Long, unit: DateTimeUnit.DateBased): LocalDate

208

fun LocalDate.minus(value: Int, unit: DateTimeUnit.DateBased): LocalDate

209

fun LocalDate.minus(value: Long, unit: DateTimeUnit.DateBased): LocalDate

210

fun LocalDate.until(other: LocalDate, unit: DateTimeUnit.DateBased): Long

211

```

212

213

### Usage Examples

214

215

```kotlin

216

// Using predefined units

217

val instant = Clock.System.now()

218

val timeZone = TimeZone.currentSystemDefault()

219

220

// Time-based units (no timezone needed)

221

val oneHourLater = instant.plus(1, DateTimeUnit.HOUR)

222

val thirtySecondsEarlier = instant.minus(30, DateTimeUnit.SECOND)

223

224

// Date-based units (timezone required for Instant)

225

val oneDayLater = instant.plus(1, DateTimeUnit.DAY, timeZone)

226

val threeMonthsLater = instant.plus(3, DateTimeUnit.MONTH, timeZone)

227

228

// Custom units

229

val tenDays = DateTimeUnit.DayBased(10)

230

val sixMonths = DateTimeUnit.MonthBased(6)

231

val fiveMinutes = DateTimeUnit.TimeBased(5.minutes)

232

233

// Unit multiplication

234

val twoWeeks = DateTimeUnit.WEEK * 2

235

val threeQuarters = 3 * DateTimeUnit.QUARTER

236

237

// With LocalDate (only date-based units)

238

val date = LocalDate(2023, 6, 15)

239

val futureDate = date.plus(2, DateTimeUnit.MONTH)

240

val monthsBetween = date.until(futureDate, DateTimeUnit.MONTH)

241

242

// Calculate differences

243

val daysBetween = date.until(futureDate, DateTimeUnit.DAY)

244

val weeksBetween = date.until(futureDate, DateTimeUnit.WEEK)

245

```

246

247

## Working with Periods vs Units

248

249

### When to Use DateTimePeriod/DatePeriod

250

251

- Representing a combination of different time components (e.g., "2 years, 3 months, and 5 days")

252

- Storing the result of period calculations between two dates/instants

253

- Serializing/deserializing period information

254

- When you need all components preserved separately

255

256

```kotlin

257

// Period example - combination of components

258

val complexPeriod = DateTimePeriod(years = 2, months = 3, days = 5, hours = 4)

259

val instant = Clock.System.now()

260

val futureInstant = instant.plus(complexPeriod, TimeZone.currentSystemDefault())

261

```

262

263

### When to Use DateTimeUnit

264

265

- Performing arithmetic with a single unit type (e.g., "add 5 days")

266

- Measuring differences in specific units (e.g., "how many weeks between these dates?")

267

- Creating regular intervals or recurring events

268

- When you need precise control over the arithmetic operation

269

270

```kotlin

271

// Unit example - single unit arithmetic

272

val date = LocalDate(2023, 1, 1)

273

val futureDate = date.plus(30, DateTimeUnit.DAY)

274

val daysBetween = date.until(futureDate, DateTimeUnit.DAY) // returns 30

275

276

// Custom intervals

277

val biweekly = DateTimeUnit.WEEK * 2

278

val quarterly = DateTimeUnit.MONTH * 3

279

```

280

281

## Edge Cases and Considerations

282

283

### Time Zone Transitions

284

285

Date-based arithmetic accounts for daylight saving time and timezone rule changes:

286

287

```kotlin

288

// DST transition example

289

val timeZone = TimeZone.of("Europe/London")

290

val springForward = LocalDateTime(2023, 3, 26, 1, 30) // Before DST

291

val instant = springForward.toInstant(timeZone)

292

293

// Adding 1 hour might skip over the "missing" hour

294

val oneHourLater = instant.plus(1, DateTimeUnit.HOUR)

295

val localTime = oneHourLater.toLocalDateTime(timeZone) // 03:30, not 02:30

296

```

297

298

### Month Length Variations

299

300

Month arithmetic handles varying month lengths appropriately:

301

302

```kotlin

303

val january31 = LocalDate(2023, 1, 31)

304

val february = january31.plus(1, DateTimeUnit.MONTH) // 2023-02-28 (not 2023-02-31)

305

306

val leap = LocalDate(2024, 2, 29) // Leap year

307

val nextYear = leap.plus(1, DateTimeUnit.YEAR) // 2025-02-28 (leap day doesn't exist)

308

```

309

310

### Normalization

311

312

Periods are automatically normalized:

313

314

```kotlin

315

val period1 = DateTimePeriod(months = 24, hours = 2, minutes = 63)

316

val period2 = DateTimePeriod(years = 2, hours = 3, minutes = 3)

317

// period1 and period2 are equivalent after normalization

318

```