The full documentation for Timex is located here.
Learn how to add Timex to your Elixir project and start using it.
To use Timex with your projects, edit your mix.exs
file and add it as a dependency:
defp deps do
[{:timex, "~> x.x.x"}]
end
defp application do
[applications: [:tzdata]]
end
To use Timex modules without the Timex namespace, add use Timex
to the top of each module you plan on referencing Timex from. You can then reference the modules directly, for example: Date.now
, versus Timex.Date.now
. This is for compatibility with other libraries which might define their own Date/DateTime/Time implementations. You can also alias individual modules if that suits your needs better, but for purposes of this documentation, we'll assume that you're going the use Timex
route.
The goal of this project is to provide a complete set of Date/Time functionality for Elixir projects, with the hope of being eventually merged into the standard library.
There are a small set of core modules you'll deal with for most tasks with Timex: Date
, Time
, Timezone
, and DateFormat
. A brief description of each is below, and they will be covered in more detail on their own pages.
The Date
module is for creating, manipulating, and converting to/from DateTime structs (which represents a combined date and time + timezone). You can create a date in any timezone in the Olson timezone database, convert an Erlang datetime tuple to a DateTime struct, shift dates in time (which transparently handles timezone transitions), shift them across timezones, and query metadata about datetimes, such as what the ISO week of that date was, etc. You can diff two dates, compare them for sorting, and more.
The Time
module supports a finer grained level of arithmetic over time intervals. It is intended for use as timestamps in logs, measuring code execution times, converting time units, etc. It does not care about timezones, but is rather used to represent a given moment in time down to the nanosecond.
The Timezone
module is used primarily for converting a DateTime to a new timezone, fetching a TimezoneInfo struct (which contains metadata about the timezone for a given zone, i.e. "America/Chicago" and point in time), or for determining the offset in minutes betweeen a given DateTime and a target timezone (Timezone.diff/2
).
The DateFormat
module is used for formatting DateTimes as strings, and parsing DateTimes from strings. In both cases you provide a format string using one of two different formatters ("default" and "strftime"). This module is extensible, and allows you to implement your own parsers/formatters if desired.
Some common scenarios with examples.
> Date.now
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 45, month: 6,
ms: 730, second: 8,
timezone: %TimezoneInfo{abbreviation: "UTC", from: :min,
full_name: "UTC", offset_std: 0, offset_utc: 0, until: :max}, year: 2015}
> Date.local
%DateTime{calendar: :gregorian, day: 23, hour: 23, minute: 45, month: 6,
ms: 713, second: 58,
timezone: %TimezoneInfo{abbreviation: "CDT",
from: {:sunday, {{2015, 3, 8}, {2, 0, 0}}}, full_name: "America/Chicago",
offset_std: 60, offset_utc: -360,
until: {:sunday, {{2015, 11, 1}, {1, 0, 0}}}}, year: 2015}
> Date.now("Europe/Copenhagen")
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 50, month: 6,
ms: 308, second: 34,
timezone: %TimezoneInfo{abbreviation: "CEST",
from: {:sunday, {{2015, 3, 29}, {2, 0, 0}}}, full_name: "Europe/Copenhagen",
offset_std: 60, offset_utc: 60,
until: {:sunday, {{2015, 10, 25}, {2, 0, 0}}}}, year: 2015}
> Date.from({{2015, 6, 24}, {4, 50, 34}})
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 50, month: 6,
ms: 0, second: 34,
timezone: %TimezoneInfo{abbreviation: "UTC", from: :min,
full_name: "UTC", offset_std: 0, offset_utc: 0, until: :max}, year: 2015}
> Date.from({{2015, 6, 24}, {4, 50, 34}}, :local)
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 50, month: 6,
ms: 0, second: 34,
timezone: %TimezoneInfo{abbreviation: "CDT",
from: {:sunday, {{2015, 3, 8}, {2, 0, 0}}}, full_name: "America/Chicago",
offset_std: 60, offset_utc: -360,
until: {:sunday, {{2015, 11, 1}, {1, 0, 0}}}}, year: 2015}
> Date.from({{2015, 6, 24}, {4, 50, 34}}, "Europe/Copenhagen")
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 50, month: 6,
ms: 0, second: 34,
timezone: %TimezoneInfo{abbreviation: "CEST",
from: {:sunday, {{2015, 3, 29}, {2, 0, 0}}}, full_name: "Europe/Copenhagen",
offset_std: 60, offset_utc: 60,
until: {:sunday, {{2015, 10, 25}, {2, 0, 0}}}}, year: 2015}
# With timezone offset
> date = "2015-06-24T04:50:34-0500"
> date |> DateFormat.parse("{ISO}")
{:ok,
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 50, month: 6,
ms: 0, second: 34,
timezone: %TimezoneInfo{abbreviation: "GMT+5", from: :min,
full_name: "Etc/GMT+5", offset_std: 0, offset_utc: -300, until: :max},
year: 2015}}
# Without timezone offset
> date = "2015-06-24T04:50:34Z"
> date |> DateFormat.parse("{ISOz}")
{:ok,
%DateTime{calendar: :gregorian, day: 24, hour: 4, minute: 50, month: 6,
ms: 0, second: 34,
timezone: %TimezoneInfo{abbreviation: "UTC", from: :min,
full_name: "UTC", offset_std: 0, offset_utc: 0, until: :max}, year: 2015}}
> Date.local |> DateFormat.format("{ISO}")
{:ok, "2015-06-24T00:04:09.293-0500"}
> Date.local |> DateFormat.format("{ISOz}")
{:ok, "2015-06-24T05:04:13.910Z"}
How to work with Erlang datetime and time representations.
Without Timex, you've probably been working with Erlang's standard library :calendar
module and/or :os.timestamp
function, you may have code which already works on them, or need to consume them from another library, etc. The two most common representations of time in Erlang are the datetime and timestamp tuples, {{year, month, day}, {hour, minute, second}}
, and {megaseconds, seconds, microseconds}
respectively. The former is of course used for representing dates and times in a familiar format, the latter is used for representing precise moments in time, down to the microsecond.
# To bring the aliases for Timex's modules into scope, we need to "use" Timex
> use Timex
# Our input datetime
> date = :calendar.universal_time
{{2015, 6, 24}, {3, 59, 5}}
# The simplest case, converting a date from Erlang form to DateTime (in universal time)
> date |> Date.from
%DateTime{
calendar: :gregorian,
year: 2015, day: 24, hour: 4, minute: 0, month: 6, ms: 0, second: 11,
timezone: %TimezoneInfo{
abbreviation: "UTC", from: :min, full_name: "UTC", offset_std: 0, offset_utc: 0, until: :max
}
}
# I'll truncate the output for further examples, our next is converting a local datetime tuple
> date = :calendar.local_time
{{2015, 6, 23}, {23, 8, 21}}
> tz = Timezone.local
%TimezoneInfo{abbreviation: "CDT", full_name: "America/Chicago", ...}
> date |> Date.from(tz)
%DateTime{..., hour: 23, minute: 8, second: 21,
timezone: %TimezoneInfo{abbreviation: "CDT", full_name: "America/Chicago", ...}
}
# You can also convert from universal to a given timezone during creation, like so:
> :calendar.universal_time |> Date.from("Europe/Copenhagen")
%DateTime{..., month: 6, day: 24, hour: 4, minute: 13, second: 31, timezone: %TimezoneInfo{abbreviation: "CEST", full_name: "Europe/Copenhagen", ...}
}
# The simplest case, converting from a timestamp to a DateTime, using the highest precision
> time = :os.timestamp
{1435, 119513, 829885}
> time |> Date.from(:timestamp)
%DateTime{..., year: 2015, month: 6, day: 24, hour: 4, minute: 18, second: 33, ms: 830, timezone: %TimezoneInfo{abbreviation: "UTC", ...}}
# Alternatively if you want control over the precision (in this example, we only care about up-to-the-second precision):
> time |> Time.to_secs |> Date.from(:secs)
%DateTime{..., year: 2015, month: 6, day: 24, hour: 4, minute: 18, second: 33, ms: 0, timezone: %TimezoneInfo{abbreviation: "UTC", ...}}
# Use the Date.Convert module (aliased to DateConvert with "use Timex")
> date = Date.now
%DateTime{..., year: 2015, month: 6, day: 24, hour: 4, minute: 18, second: 33, ms: 0, ...}
> date |> DateConvert.to_erlang_datetime
{{2015, 6, 24}, {4, 18, 33}}
# You can also produce a variant of the Erlang datetime tuple which also contains the timezone offset (in hours) and abbreviation:
> Date.local |> DateConvert.to_gregorian
{{2015, 6, 23}, {23, 28, 47}, {1.0, "CDT"}}
Which functions provide microsecond precision?
If you need to work with time intervals down to microsecond precision, you should take a look at the functions in the Time
module. The Date
module is designed for things like handling different time zones and working with dates separated by large intervals, so the minimum time unit it uses is milliseconds.
So how do I work with time intervals defined with microsecond precision?
Use functions from the Time
module for time interval arithmetic.
How do I find the time interval between two dates?
Use Date.diff
to obtain the number of milliseconds, seconds, minutes, hours, days, months, weeks, or years between two dates.
What is the support for timezones?
Full support for retrieving local timezone configuration on OSX, *NIX, and Windows, conversion to any timezone in the Olson timezone database, and full support for timezone transitions.
Timezone support is also exposed via the Timezone
, and Timezone.Local
modules. Their functionality is also exposed via the Date
module's API, and most common use cases shouldn't need to access the Timezone
namespace directly, but it's there if needed.
This software is licensed under the MIT license.