Parsing a Twitter timestamp with Elixir

Timestamps from Twitter's API are jacked up. At a quick glance, it may just look like any other timestamp.

"Mon Dec 12 23:03:14 +0000 2016"

Right, that is a reasonable way to represent a point in time. Start with an abbreviation of the day of the week and then sandwich the time in the middle of the date.

Unfortunately, most date parsers are not going to be particularly happy with this representation. My task was to figure out how to convert this kind of timestamp into an Ecto.DateTime struct. Along the way I learned a little about RFC1123 and Elixir's Timex package.

RFC822 and RFC1123

RFC822 and RFC1123 define date and time specification. They state that a timestamp can optionally begin with an abbreviated day of week (with a comma) followed by the date and then the time. The full details including a specification of the syntax can be found in RFC822. RFC1123 states that the year should be specified with four, instead of two, digits.

The upshot is that a timestamp should look like this

Tue, 06 Mar 2013 01:25:19 +0200  

or this

06 Mar 2013 01:25:19 +0200  

Timex

The Timex package, "a complete date/time library for Elixir projects," is a great way to work with dates and times.

It comes with a number of built-in formats for parsing and formatting timestamps including the RFC1123 format.

> Timex.parse!("Tue, 06 Mar 2013 01:25:19 +0200", "{RFC1123}")
#<DateTime(2013-03-06T01:25:19+02:00 Etc/GMT-2)>

Parsing Twitter's Timestamp

With these things in mind, I decided the best way forward was to transform the timestamp Twitter gives me into an RFC1123-compliant timestamp, parse it with Timex, and then create the Ecto.DateTime struct from that.

defmodule TwitterAPIHelper do  
  def cast_timestamp(timestamp) do
    [dow, mon, day, time, zone, year] = String.split(timestamp, " ")
    rfc1123 = Enum.join(["#{dow},", day, mon, year, time, zone], " ")

    rfc1123
    |> Timex.parse!("{RFC1123}")
    |> Ecto.DateTime.cast!()
  end
end

> TwitterAPIHelper.cast_timestamp("Mon Dec 12 23:03:14 +0000 2016")
#Ecto.DateTime<2016-12-12 23:03:14>

Voila! I now have a representation of the Twitter API's timestamp that I can insert into my database.