Timex

MasterHex.pm VersionInchCICoverage Status

Timex is a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package. If you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you! It is very easy to use Timex types in place of default Erlang types, as well as Ecto types via the timex_ecto package.

The complete documentation for Timex is located here.

Migrating to Timex 2.x

See the Migrating section further down for details.

Getting Started

There are some brief examples on usage below, but I highly recommend you review the API docs here, there are many examples, and some extra pages with richer documentation on specific subjects such as custom formatters/parsers, etc.

Adding Timex To Your Project

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: [:timex]]
end

Quickfast introduction

To use Timex, I recommend you add use Timex to the top of the module where you will be working with Timex modules, all it does is alias common types so you can work with them more comfortably. If you want to see the specific aliases added, check the top of the Timex module, in the __using__/1 macro definition.

Here’s a few simple examples:

> use Timex
> date = Date.today
%Date{year: 2016, month: 2, day: 29}

> datetime = DateTime.today
%DateTime{year: 2016, month: 2, day: 29,
          hour: 12, minute: 30, second: 30, millisecond: 120, timezone: %TimezoneInfo{...}}

> timestamp = Time.now
{1457, 137754, 906908}

> default_str = Timex.format(datetime, "{ISO:Extended}")
{:ok, "2016-02-29T12:30:30.120+00:00"}

> strftime_str = Timex.format(datetime, "%FT%T%:z", :strftime)
{:ok, "2016-02-29T12:30:30+00:00"}

> Timex.parse(default_str, "{ISO:Extended}")
{:ok, %DateTime{...}}

> Timex.parse(strftime_str, "%FT%T%:z", :strftime)
{:ok, %DateTime{...}}

> Time.diff(Time.now, Time.zero, :days)
16850

> Timex.shift(date, days: 3)
%Date{year: 2016, month: 3, day: 3}

> Timex.shift(date, hours: 2, minutes: 13)
%DateTime{year: 2016, month: 2, day: 29,
          hour: 14, minute: 43, second: 30, millisecond: 120, timezone: %TimezoneInfo{...}}

> timezone = Timex.timezone("America/Chicago", DateTime.today)
%Timex.TimezoneInfo{abbreviation: "CST",
 from: {:sunday, {{2015, 11, 1}, {1, 0, 0}}}, full_name: "America/Chicago",
 offset_std: 0, offset_utc: -360, until: {:sunday, {{2016, 3, 13}, {2, 0, 0}}}}

> Timezone.convert(datetime, timezone)
%DateTime{year: 2016, month: 2, day: 29,
          hour: 6, minute: 30, second: 30, millisecond: 120,
          timezone: %TimezoneInfo{abbreviation: "CST", ...}}

> Timex.equal?(Date.today, DateTime.today)
true

> Timex.before?(Date.today, Timex.shift(Date.today, days: 1))
true

There are a ton of other functions for Dates, Times, and DateTimes, way more than can be covered here. Hopefully the above gives you a taste of what the API is like!

Extensibility

Timex exposes a number of extension points for you, in order to accomodate different use cases:

You can use custom Date/DateTime types with Timex via the Timex.Convertable protocol, which gives you a way to convert your type to various Timex types, and then use the Timex API to manipulate them, for example, you could use the Calendar library’s types with Timex via Comparable, or Ecto’s, or your own!

You can compare/diff custom Date/DateTime types with Timex via the Timex.Comparable protocol, which also understands types which implement Timex.Convertable, allowing you to use Comparable as soon as you’ve implemented Convertable!

The same is true for Timex’s API in general - if you pass a type which implements Timex.Convertable, and the type is not a native Timex one, it will be coerced to one via that protocol.

You can provide your own formatter/parser for Date/DateTime strings by implementing the Timex.Format.DateTime.Formatter and/or Timex.Parse.DateTime.Parser behaviours, depending on your needs.

Common Issues

Warning: Timex functions of the form iso_* behave based on how the ISO calendar represents dates/times and not the ISO8601 date format. This confusion has occured before, and it’s important to note this!

Migrating

If you have been using Timex pre-2.x, and you are looking to migrate, it’s fairly painless, but important to review the list of breaking changes and new features.

Overview of 2.x changes

Please see the CHANGELOG.md file for the list of all changes made, below are a brief recap of the major points, and instructions on how to migrate your existing Timex-based code to 2.x. I promise it’s easy!

There was a significant amount of general project improvements done as part of this release as well:

Migration steps (1.x -> 2.x)

Depending on how heavily you are using the various features of Timex’s API, the migration can be anywhere from 15 minutes to a couple of hours, but the steps below are a guide which should help the process go smoothly. For the vast majority of folks, I anticipate that it will be a very small time investment.

  1. Change all Timex.Date references to Timex, except those which are creating DateTime values, such as Date.now, those references should be changed to point to DateTime now.
  2. Change all DateFormat references to Timex, DateFormat was removed.
  3. Change all Timex.Date.Convert or DateConvert references to Timex or Timex.Convertable, the former have become the latter
  4. Make sure you upgrade timex_ecto as well if you are using it with your project
  5. Compile, if you get warnings about missing methods on Timex, they are type-specific functions for DateTime, so change those references to Timex.DateTime
  6. You’ll need to modify your code to handle error tuples instead of exceptions
  7. You’ll need to handle the new AmbiguousDateTime and AmbiguousTimezoneInfo structs, the best approach is to pattern match on API return values, use DateTime if it was given, or select :before or :after values from the Ambiguous* structs. Your code will become a lot safer as a result of this change!
  8. Unit names are soft-deprecated for now, but you’ll want to change references to abbreviated units like secs to their full names (i.e. seconds) in order to make the stderr warnings go away.

And that’s it! If you have any issues migrating, please ping me, and I’ll be glad to help. If you have a dependency that uses Timex which you’d like to get updated to 2.x, open an issue here, and I’ll submit a PR to those projects to help bring them up to speed quicker.

Roadmap

The following are an unordered list of things I plan for Timex in the future, if you have specific requests, please open an issue with “RFC” in the title, and we can discuss it, and hopefully get input from the community.

License

This software is licensed under the MIT license.