Esc
Start typing to search...

Temporal Types

Keel provides dedicated types for working with dates, times, and durations. Each has its own module with creation, parsing, formatting, arithmetic, and comparison functions.

Date

The Date type represents a calendar date (year, month, day) without a time component.

Creating Dates

-- tags: date, creation
-- expect: Ok 2024-03-15
-- Creating dates from year, month, day
import Date

Date.fromYmd 2024 3 15
Try it

Parsing Dates

Parse from ISO 8601 format or a custom strftime format:

-- tags: date, parsing
-- expect: Ok 2024-06-15
-- Parsing dates from strings
import Date

Date.parseIso "2024-06-15"
Try it
-- Custom format
Date.parse "%d/%m/%Y" "15/06/2024"

Date Components

-- tags: date, components
-- expect: (2024, 3, 15)
-- Extracting date components
import Date

let date = case Date.fromYmd 2024 3 15 of
    Ok d -> d
    Err _ -> Date.today ()

(Date.year date, Date.month date, Date.day date)
Try it

Other components include weekday (1=Monday, 7=Sunday), dayOfYear, weekNumber, isLeapYear, and daysInMonth.

Date Arithmetic

-- tags: date, arithmetic
-- expect: "2024-04-14"
-- Date arithmetic
import Date

let date = case Date.fromYmd 2024 3 15 of
    Ok d -> d
    Err _ -> Date.today ()

-- Add 30 days
let later = Date.addDays 30 date

Date.toIsoString later
Try it

Available operations: addDays, addWeeks, addMonths, addYears. Month and year addition handles edge cases (e.g., Jan 31 + 1 month = Feb 28).

Comparing Dates

-- tags: date, comparison
-- expect: 31
-- Comparing dates and computing differences
import Date

let start = case Date.fromYmd 2024 1 1 of
    Ok d -> d
    Err _ -> Date.today ()

let end = case Date.fromYmd 2024 2 1 of
    Ok d -> d
    Err _ -> Date.today ()

Date.diffDays start end
Try it

Comparison functions: isBefore, isAfter, isEqual, compare, diffDays.

Time

The Time type represents a time of day (hour, minute, second) without a date component.

Creating Times

-- tags: time, creation
-- expect: Ok 14:30:00
-- Creating time values
import Time

Time.fromHms 14 30 0
Try it

Convenience constructors: midnight () returns 00:00:00, noon () returns 12:00:00.

Parsing Times

-- tags: time, parsing
-- expect: Ok 09:15:30
-- Parsing time from strings
import Time

Time.parseIso "09:15:30"
Try it

Time Components

-- tags: time, components
-- expect: (14, 30, 0)
-- Extracting time components
import Time

let t = case Time.fromHms 14 30 0 of
    Ok t -> t
    Err _ -> Time.midnight ()

(Time.hour t, Time.minute t, Time.second t)
Try it

Time Arithmetic

-- tags: time, arithmetic
-- expect: "15:15:00"
-- Time arithmetic
import Time

let t = case Time.fromHms 14 30 0 of
    Ok t -> t
    Err _ -> Time.midnight ()

-- Add 45 minutes
let later = Time.addMinutes 45 t

Time.toIsoString later
Try it

Available operations: addHours, addMinutes, addSeconds. Time wraps around midnight (e.g., 23:00 + 2 hours = 01:00).

Duration

The Duration type represents a span of time, which can be positive or negative.

Creating Durations

-- tags: duration, creation
-- expect: 7200
-- Creating and converting durations
import Duration

let twoHours = Duration.fromHours 2

Duration.toSeconds twoHours
Try it

Creation functions: fromMillis, fromSeconds, fromMinutes, fromHours, fromDays, fromWeeks, zero.

Duration Arithmetic

-- tags: duration, arithmetic
-- expect: Ok 5400
-- Duration arithmetic
import Duration

let oneHour = Duration.fromHours 1
let thirtyMin = Duration.fromMinutes 30

case Duration.add oneHour thirtyMin of
    Ok d -> Duration.toSeconds d
    Err _ -> 0
Try it

Operations: add, sub, mul, div, negate, abs. Arithmetic returns Result Duration DurationError for overflow safety.

Converting Between Units

-- tags: duration, conversion
-- expect: 2
-- Converting between duration units
import Duration

let d = Duration.fromMinutes 150

-- Get total hours (truncated)
Duration.toHours d
Try it

Conversion functions: toMillis, toSeconds, toMinutes, toHours, toDays, toWeeks.

DateTime Interop

The DateTime module provides functions to convert between Date, Time, and DateTime:

Extract Date or Time

-- tags: datetime, date, interop
-- expect: 2024
-- Extract Date component from DateTime
import DateTime
import Date

let dt = case DateTime.fromDate 2024 6 15 of
    Just d -> d
    Nothing -> DateTime.now ()

let date = DateTime.getDate dt
Date.year date
Try it
-- tags: datetime, time, interop
-- expect: 14
-- Extract Time component from DateTime
import DateTime
import Time

let dt = case DateTime.fromParts 2024 6 15 14 30 0 of
    Just d -> d
    Nothing -> DateTime.now ()

let time = DateTime.getTime dt
Time.hour time
Try it

Combine Date and Time

-- tags: datetime, date, time, interop
-- expect: "2024-06-15T14:30:00+00:00"
-- Combine Date and Time into DateTime
import DateTime
import Date
import Time

let date = case Date.fromYmd 2024 6 15 of
    Ok d -> d
    Err _ -> Date.today ()

let time = case Time.fromHms 14 30 0 of
    Ok t -> t
    Err _ -> Time.midnight ()

let dt = DateTime.combine date time
DateTime.formatRfc3339 dt
Try it

Convert Date to DateTime

-- tags: datetime, date, interop
-- expect: 0
-- Convert Date to DateTime at midnight UTC
import DateTime
import Date

let date = case Date.fromYmd 2024 1 1 of
    Ok d -> d
    Err _ -> Date.today ()

let dt = DateTime.fromDateType date
DateTime.hour dt
Try it

Error Handling

Date and Time functions that can fail return typed error results:

import Date

-- Invalid date returns a typed error
case Date.fromYmd 2024 2 30 of
    Ok date -> Date.toIsoString date
    Err Date::InvalidDay -> "Invalid day for this month"
    Err _ -> "Other error"

Error variants for DateError: InvalidMonth, InvalidDay, InvalidDate, ParseError. Error variants for TimeError: InvalidHour, InvalidMinute, InvalidSecond, InvalidNanosecond, InvalidTime, ParseError.

Next Steps

See the individual stdlib module pages for complete function references: Date, Time, Duration, DateTime.