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 itParsing 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 itOther 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 itAvailable 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 itComparison 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 itConvenience 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 itTime 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 itTime 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 itAvailable 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 itCreation 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 itOperations: 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 itConversion 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 itCombine 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 itConvert 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 itError 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.