Search results

There are no results.

std.time.DateTime

class pub DateTime

An object representing the current system time.

Internally the time is represented as the number of seconds since the Unix epoch, excluding leap seconds.

DateTime is based on the Gregorian calendar, and doesn't support additional calendars such as the Julian calendar.

If you want to measure the duration between two events, it's best to use the Instant type, as it's not affected by external factors such as clock adjustments and leap seconds.

Fields

year

let pub @year: Int

The year.

month

let pub @month: Int

The month, from 1 to 12.

day

let pub @day: Int

The day, from 1 to 31.

hour

let pub @hour: Int

The hour, from 0 to 23.

minute

let pub @minute: Int

The minute, from 0 to 59.

second

let pub @second: Int

The second, from 0 to 59.

sub_second

let pub @sub_second: Float

The sub seconds.

utc_offset

let pub @utc_offset: Int

The UTC offset (in seconds).

Static methods

from_timestamp

Show source code
Hide source code
fn pub static from_timestamp[T: ToFloat](
  time: ref T,
  utc_offset: Int,
) -> DateTime {
  # This implementation is based on the algorithms as described on
  # http://howardhinnant.github.io/date_algorithms.html, specifically the
  # `civil_from_days()` algorithm.
  #
  # To be truly honest, at the time of writing I didn't fully understand the
  # algorithm, and reading through the linked article made my head spin. But
  # it works, so ship it!
  #
  # Important note: this algorithm works because Inko implements integer
  # divisions as floored divisions (like e.g. Python and Ruby), instead of
  # rounding towards zero (like Rust and C).
  let time = time.to_float
  let epoch_secs = time.to_int + utc_offset
  let epoch_days = (epoch_secs / SECS_PER_DAY) + 719_468
  let era = if epoch_days >= 0 { epoch_days } else { epoch_days - 146_096 }
    / 146_097
  let doe = epoch_days - (era * 146_097)
  let yoe = (doe - (doe / 1460) + (doe / 36_524) - (doe / 146_096)) / 365
  let doy = doe - ((365 * yoe) + (yoe / 4) - (yoe / 100))
  let mp = ((5 * doy) + 2) / 153
  let day = doy - ((153 * mp) + 2 / 5) + 1
  let month = if mp < 10 { mp + 3 } else { mp - 9 }
  let mut year = yoe + (era * 400)

  if month <= 2 { year += 1 }

  # The number of seconds since the start of the day.
  let mut day_secs = epoch_secs - ((epoch_secs / SECS_PER_DAY) * SECS_PER_DAY)
  let second = day_secs % 60
  let minute = (day_secs % SECS_PER_HOUR) / 60
  let hour = day_secs / SECS_PER_HOUR

  DateTime(
    year: year,
    month: month,
    day: day,
    hour: hour,
    minute: minute,
    second: second,
    sub_second: time.fractional,
    utc_offset: utc_offset,
  )
}
fn pub static from_timestamp[T: ToFloat](time: ref T, utc_offset: Int) -> DateTime

Returns a new DateTime from a Unix timestamp and UTC offset.

The time argument is the number of seconds since or before the Unix epoch.

Example

import std.time (DateTime)

DateTime.from_timestamp(time: 1661546853, utc_offset: 0).year # => 2022

new

Show source code
Hide source code
fn pub static new -> DateTime {
  from_timestamp(inko_time_system, inko_time_system_offset as Int)
}
fn pub static new -> DateTime

Returns a new DateTime representing the current time using the local timezone.

Examples

Getting the current time:

import std.time (DateTime)

DateTime.new

utc

Show source code
Hide source code
fn pub static utc -> DateTime {
  from_timestamp(time: inko_time_system, utc_offset: 0)
}
fn pub static utc -> DateTime

Returns a new DateTime representing the current time using UTC as the timezone.

Examples

Getting the current time in UTC:

import std.time (DateTime)

DateTime.utc

Instance methods

!=

Show source code
Hide source code
fn pub !=(other: T) -> Bool {
  (self == other).false?
}
fn pub !=(other: T) -> Bool

Returns true if self and the given object are not equal to each other.

+

Show source code
Hide source code
fn pub +(other: ref Duration) -> DateTime {
  let timestamp = to_float + other.to_secs

  DateTime.from_timestamp(timestamp, utc_offset: @utc_offset)
}
fn pub +(other: ref Duration) -> DateTime

Adds the given object to self.

-

Show source code
Hide source code
fn pub -(other: ref Duration) -> DateTime {
  let timestamp = to_float - other.to_secs

  DateTime.from_timestamp(timestamp, utc_offset: @utc_offset)
}
fn pub -(other: ref Duration) -> DateTime

Subtracts the given object from self.

<

Show source code
Hide source code
fn pub <(other: ref T) -> Bool {
  match cmp(other) {
    case Less -> true
    case _ -> false
  }
}
fn pub <(other: ref T) -> Bool

Returns true if self is lower than the given argument.

<=

Show source code
Hide source code
fn pub <=(other: ref T) -> Bool {
  match cmp(other) {
    case Less or Equal -> true
    case _ -> false
  }
}
fn pub <=(other: ref T) -> Bool

Returns true if self is lower than or equal to the given argument.

==

Show source code
Hide source code
fn pub ==(other: ref DateTime) -> Bool {
  @year == other.year
    and @month == other.month
    and @day == other.day
    and @hour == other.hour
    and @minute == other.minute
    and @second == other.second
    and @sub_second == other.sub_second
    and @utc_offset == other.utc_offset
}
fn pub ==(other: ref DateTime) -> Bool

Returns true if self and the given object are equal to each other.

This operator is used to perform structural equality. This means two objects residing in different memory locations may be considered equal, provided their structure is equal. For example, two different arrays may be considered to have structural equality if they contain the exact same values.

>

Show source code
Hide source code
fn pub >(other: ref T) -> Bool {
  match cmp(other) {
    case Greater -> true
    case _ -> false
  }
}
fn pub >(other: ref T) -> Bool

Returns true if self is greater than the given argument.

>=

Show source code
Hide source code
fn pub >=(other: ref T) -> Bool {
  match cmp(other) {
    case Greater or Equal -> true
    case _ -> false
  }
}
fn pub >=(other: ref T) -> Bool

Returns true if self is equal to or greater than the given argument.

clone

Show source code
Hide source code
fn pub clone -> DateTime {
  DateTime(
    year: @year,
    month: @month,
    day: @day,
    hour: @hour,
    minute: @minute,
    second: @second,
    sub_second: @sub_second,
    utc_offset: @utc_offset,
  )
}
fn pub clone -> DateTime

Creates a clone of self.

cmp

Show source code
Hide source code
fn pub cmp(other: ref DateTime) -> Ordering {
  to_float.cmp(other.to_float)
}
fn pub cmp(other: ref DateTime) -> Ordering

Returns the ordering between self and the given argument.

The returned value should be as follows:

  • a == b: Ordering.Equal
  • a > b: Ordering.Greater
  • a < b: Ordering.Less

day_of_week

Show source code
Hide source code
fn pub day_of_week -> Int {
  # January 1st, 1970 (our anchor date) was on a Thursday. We add 3 so that
  # Monday (3 days before Thursday) becomes the anchor date.
  #
  # We later on add 1 since the % operator will return 0 for Monday (since its
  # the first value in the range), but week days range from 1 to 7; not 0 to
  # 6.
  #
  # The following table should help illustrate this:
  #
  # | Date       | Day of week | days_since_unix_epoch
  # |:-----------|:------------|:----------------------
  # | 1969-12-29 | Monday      | -3
  # | 1969-12-30 | Tuesday     | -2
  # | 1969-12-31 | Wednesday   | -1
  # | 1970-01-01 | Thursday    | 0
  # | 1970-01-02 | Friday      | 1
  # | 1970-01-03 | Saturday    | 2
  # | 1970-01-04 | Sunday      | 3
  #
  # For these dates, the calculations would be as follows:
  #
  # | Date       | Calculation        | Simplified  | Return value
  # |:-----------|:-------------------|:------------|:------------
  # | 1969-12-29 | ((-3 + 3) % 7) + 1 | (0 % 7) + 1 | 1
  # | 1969-12-30 | ((-2 + 3) % 7) + 1 | (1 % 7) + 1 | 2
  # | 1969-12-31 | ((-1 + 3) % 7) + 1 | (2 % 7) + 1 | 3
  # | 1970-01-01 | ((0 + 3) % 7) + 1  | (3 % 7) + 1 | 4
  # | 1970-01-02 | ((1 + 3) % 7) + 1  | (4 % 7) + 1 | 5
  # | 1970-01-03 | ((2 + 3) % 7) + 1  | (5 % 7) + 1 | 6
  # | 1970-01-04 | ((3 + 3) % 7) + 1  | (6 % 7) + 1 | 7
  days_since_unix_epoch + 3 % DAYS_PER_WEEK + 1
}
fn pub day_of_week -> Int

Returns the day of the week from 1 to 7.

Per ISO 8601 the first day of the week starts on Monday, not Sunday.

day_of_year

Show source code
Hide source code
fn pub day_of_year -> Int {
  let days = if leap_year? { LEAP_DAYS } else { NORMAL_DAYS }

  days.get(@month - 1) + @day
}
fn pub day_of_year -> Int

Returns the day of the year from 1 to 366 for leap years, and from 1 to 365 for regular years.

days_since_unix_epoch

Show source code
Hide source code
fn pub days_since_unix_epoch -> Int {
  let year = if @month <= 2 { @year - 1 } else { @year }
  let month = @month
  let era = if year >= 0 { year } else { year - 399 } / 400
  let yoe = year - (era * 400)
  let doy = (((153 * if month > 2 { month - 3 } else { month + 9 }) + 2) / 5)
    + @day
    - 1
  let doe = (yoe * 365) + (yoe / 4) - (yoe / 100) + doy

  (era * 146_097) + doe - 719_468
}
fn pub days_since_unix_epoch -> Int

Returns the number of days between self and the Unix epoch.

The returned Int is negative if self is before the Unix epoch, and positive for a value that is on or after the Unix epoch.

fmt

Show source code
Hide source code
fn pub fmt(formatter: mut Formatter) {
  let sign = if @utc_offset > 0 { '+' } else { '-' }
  let offset = if @utc_offset == 0 {
    ' UTC'
  } else {
    let hh = (@utc_offset / SECS_PER_HOUR).to_string.pad_start(
      with: '0',
      chars: 2,
    )
    let mm = (@utc_offset % SECS_PER_HOUR / 60).to_string.pad_start(
      with: '0',
      chars: 2,
    )

    ' ${sign}${hh}${mm}'
  }

  let year = @year.to_string.pad_start(with: '0', chars: 4)
  let month = @month.to_string.pad_start(with: '0', chars: 2)
  let day = @day.to_string.pad_start(with: '0', chars: 2)
  let hour = @hour.to_string.pad_start(with: '0', chars: 2)
  let min = @minute.to_string.pad_start(with: '0', chars: 2)
  let secs = @second.to_string.pad_start(with: '0', chars: 2)

  formatter.write('${year}-${month}-${day} ${hour}:${min}:${secs}${offset}')
}
fn pub fmt(formatter: mut Formatter)

Formats self in a human-readable format for debugging purposes.

leap_year?

Show source code
Hide source code
fn pub leap_year? -> Bool {
  let year = @year

  (year % 4) == 0 and ((year % 100) > 0 or (year % 400) == 0)
}
fn pub leap_year? -> Bool

Returns true if the current year is a leap year.

to_float

Show source code
Hide source code
fn pub to_float -> Float {
  to_int.to_float + @sub_second
}
fn pub to_float -> Float

Returns the timestamp since the Unix epoch, the including fractional seconds.

to_int

Show source code
Hide source code
fn pub to_int -> Int {
  let days = days_since_unix_epoch
  let days_sec = days.absolute * SECS_PER_DAY
  let time_sec = (@hour * SECS_PER_HOUR) + (@minute * SECS_PER_MIN) + @second
  let timestamp = if days < 0 {
    0 - (days_sec - time_sec)
  } else {
    days_sec + time_sec
  }

  # Timestamps are always in UTC, not in the local time.
  timestamp - @utc_offset
}
fn pub to_int -> Int

Returns the number of seconds since the Unix epoch in UTC.

This value will be negative if self is a DateTime before the Unix epoch.

to_utc

Show source code
Hide source code
fn pub to_utc -> DateTime {
  DateTime.from_timestamp(time: to_float, utc_offset: 0)
}
fn pub to_utc -> DateTime

Converts the DateTime to another DateTime that uses UTC as the timezone.

utc?

Show source code
Hide source code
fn pub utc? -> Bool {
  @utc_offset == 0
}
fn pub utc? -> Bool

Returns true if UTC is used.

Implemented traits

std.clone.

Clone

impl Clone[DateTime] for DateTime
std.cmp.

Compare

impl Compare[DateTime] for DateTime
std.cmp.

Equal

impl Equal[ref DateTime] for DateTime
std.float.

ToFloat

impl ToFloat for DateTime
std.fmt.

Format

impl Format for DateTime
std.int.

ToInt

impl ToInt for DateTime
std.ops.

Add

impl Add[Duration, DateTime] for DateTime
std.ops.

Subtract

impl Subtract[Duration, DateTime] for DateTime