DateTimeParser v1.0.0-rc.2 DateTimeParser View Source

DateTimeParser is a tokenizer for strings that attempts to parse into a DateTime, NaiveDateTime if timezone is not determined, Date, or Time.

The biggest ambiguity between datetime formats is whether it's ymd (year month day), mdy (month day year), or dmy (day month year); this is resolved by checking if there are slashes or dashes. If slashes, then it will try dmy first. All other cases will use the international format ymd. Sometimes, if the conditions are right, it can even parse dmy with dashes if the month is a vocal month (eg, "Jan").

If the string is 10-11 digits with optional precision, then we'll try to parse it as a Unix Epoch timestamp.

If the string is 1-5 digits with optional precision, then we'll try to parse it as a Serial timestamp (spreadsheet time) treating 1899-12-31 as 1. This will cause Excel-produced dates from 1900-01-01 until 1900-03-01 to be incorrect, as they really are.

digitsparserrangenotes
1-5Seriallow = 1900-01-01, high = 2173-10-15. Negative numbers go to 1626-03-17Floats indicate time. Integers do not.
6-9TokenizeranyThis allows for "20190429" to be parsed as 2019-04-29
10-11Epochlow = 1976-03-03T09:46:40, high = 5138-11-16 09:46:39If padded with 0s, then it can capture entire range. Negative numbers not yet supported

Examples

  iex> DateTimeParser.parse("19 September 2018 08:15:22 AM")
  {:ok, ~N[2018-09-19 08:15:22]}

  iex> DateTimeParser.parse_datetime("19 September 2018 08:15:22 AM")
  {:ok, ~N[2018-09-19 08:15:22]}

  iex> DateTimeParser.parse_datetime("2034-01-13", assume_time: true)
  {:ok, ~N[2034-01-13 00:00:00]}

  iex> DateTimeParser.parse_datetime("2034-01-13", assume_time: ~T[06:00:00])
  {:ok, ~N[2034-01-13 06:00:00]}

  iex> DateTimeParser.parse("invalid date 10:30pm")
  {:ok, ~T[22:30:00]}

  iex> DateTimeParser.parse("2019-03-11T99:99:99")
  {:ok, ~D[2019-03-11]}

  iex> DateTimeParser.parse("2019-03-11T10:30:00pm UNK")
  {:ok, ~N[2019-03-11T22:30:00]}

  iex> DateTimeParser.parse("2019-03-11T22:30:00.234+00:00")
  {:ok, DateTime.from_naive!(~N[2019-03-11T22:30:00.234Z], "Etc/UTC")}

  iex> DateTimeParser.parse_date("2034-01-13")
  {:ok, ~D[2034-01-13]}

  iex> DateTimeParser.parse_date("01/01/2017")
  {:ok, ~D[2017-01-01]}

  iex> DateTimeParser.parse_datetime("1564154204")
  {:ok, DateTime.from_naive!(~N[2019-07-26T15:16:44Z], "Etc/UTC")}

  iex> DateTimeParser.parse_datetime("41261.6013888889")
  {:ok, ~N[2012-12-18T14:26:00]}

  iex> DateTimeParser.parse_date("44262")
  {:ok, ~D[2021-03-07]}
  # This is a serial number date, commonly found in spreadsheets, eg: `=VALUE("03/07/2021")`

  iex> DateTimeParser.parse_datetime("1/1/18 3:24 PM")
  {:ok, ~N[2018-01-01T15:24:00]}

  iex> DateTimeParser.parse_datetime("1/1/18 3:24 PM", assume_utc: true)
  {:ok, DateTime.from_naive!(~N[2018-01-01T15:24:00Z], "Etc/UTC")}
  # or ~U[2018-01-01T15:24:00Z] in Elixir 1.9.0+

  iex> DateTimeParser.parse_datetime(~s|"Mar 28, 2018 7:39:53 AM PDT"|, to_utc: true)
  {:ok, DateTime.from_naive!(~N[2018-03-28T14:39:53Z], "Etc/UTC")}

  iex> {:ok, datetime} = DateTimeParser.parse_datetime(~s|"Mar 1, 2018 7:39:53 AM PST"|)
  iex> datetime
  #DateTime<2018-03-01 07:39:53-08:00 PST PST8PDT>

  iex> DateTimeParser.parse_datetime(~s|"Mar 1, 2018 7:39:53 AM PST"|, to_utc: true)
  {:ok, DateTime.from_naive!(~N[2018-03-01T15:39:53Z], "Etc/UTC")}

  iex> {:ok, datetime} = DateTimeParser.parse_datetime(~s|"Mar 28, 2018 7:39:53 AM PDT"|)
  iex> datetime
  #DateTime<2018-03-28 07:39:53-07:00 PDT PST8PDT>

  iex> DateTimeParser.parse_time("10:13pm")
  {:ok, ~T[22:13:00]}

  iex> DateTimeParser.parse_time("10:13:34")
  {:ok, ~T[10:13:34]}

  iex> DateTimeParser.parse_time("18:14:21.145851000000Z")
  {:ok, ~T[18:14:21.145851]}

  iex> DateTimeParser.parse_datetime(nil)
  {:error, "Could not parse nil"}

Link to this section Summary

Functions

Parse a %DateTime{}, %NaiveDateTime{}, %Date{}, or %Time{} from a string.

Parse %Date{} from a string. Accepts options parse_date_options/0

Parse a %DateTime{} or %NaiveDateTime{} from a string. Accepts options parse_datetime_options/0

Parse %Time{} from a string.

Link to this section Types

Link to this type

assume_date()

View Source
assume_date() :: {:assume_date, boolean() | Date.t()}
Link to this type

assume_time()

View Source
assume_time() :: {:assume_time, boolean() | Time.t()}
Link to this type

assume_utc()

View Source
assume_utc() :: {:assume_utc, boolean()}
Link to this type

parse_date_options()

View Source
parse_date_options() :: [assume_date()]

Options applicable for parse_date/2

  • :assume_date Default false. If a date cannot be fully determined, then it will not be assumed by default. If you supply true, then Date.utc_today() will be assumed. You can also supply your own date, and the found tokens will be merged with it.
Link to this type

parse_datetime_options()

View Source
parse_datetime_options() :: [assume_utc() | to_utc() | assume_time()]

Options applicable for parse_datetime/2

  • :assume_utc Default false. Only applicable for strings where parsing could not determine a timezone. Instead of returning a NaiveDateTime, this option will assume them to be in UTC timezone, and therefore return a DateTime. If the timezone is determined, then it will continue to be returned in the original timezone. See to_utc option to also convert it to UTC.

  • :to_utc Default false. If there's a timezone detected in the string, then attempt to convert to UTC timezone. If you know that your timestamps are in the future and are going to store it for later use, it may be better to convert to UTC and keep the original timestamp since government organizations may change timezone rules before the timestamp elapses, therefore making the UTC timestamp wrong or invalid. Check out the guide on future timestamps.

  • :assume_time Default false. If a time cannot be determined, then it will not be assumed by default. If you supply true, then ~T[00:00:00] will be assumed. You can also supply your own time, and the found tokens will be merged with it.

Options for parse/2. Combination of parse_date_options/0 and parse_datetime_options/0.

Link to this type

to_utc()

View Source
to_utc() :: {:to_utc, boolean()}

Link to this section Functions

Link to this function

parse(string, opts \\ [])

View Source
parse(String.t() | nil, parse_options()) ::
  {:ok, DateTime.t() | NaiveDateTime.t() | Date.t() | Time.t()}
  | {:error, String.t()}

Parse a %DateTime{}, %NaiveDateTime{}, %Date{}, or %Time{} from a string.

Accepts parse_options/0

Link to this function

parse_date(string, opts \\ [])

View Source
parse_date(String.t() | nil, parse_date_options()) ::
  {:ok, Date.t()} | {:error, String.t()}

Parse %Date{} from a string. Accepts options parse_date_options/0

Link to this function

parse_datetime(string, opts \\ [])

View Source
parse_datetime(String.t() | nil, parse_datetime_options()) ::
  {:ok, DateTime.t() | NaiveDateTime.t()} | {:error, String.t()}

Parse a %DateTime{} or %NaiveDateTime{} from a string. Accepts options parse_datetime_options/0

Link to this function

parse_time(string)

View Source
parse_time(String.t() | nil) :: {:ok, Time.t()} | {:error, String.t()}

Parse %Time{} from a string.