# DateTimeParser
[![Hex.pm Version](http://img.shields.io/hexpm/v/date_time_parser.svg)](https://hex.pm/packages/date_time_parser)
[![Hex docs](http://img.shields.io/badge/hex.pm-docs-blue.svg?style=flat)](https://hexdocs.pm/date_time_parser)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE.md)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](./CODE_OF_CONDUCT.md)
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.
## Planned Breaking Changes
* `parse_datetime` currently assumes `00:00:00` time if it cannot be determined.
This will likely change in a future version because it's better to have no
information than have wrong information. If you want to assume `00:00:00`,
that's fine, but this library shouldn't assume it for you, or at least make
it an option.
* `parse_datetime` currently defaults to converting to UTC when the timezone is
known. This default may change to keep the original timezone information.
This will help for future timestamps since timezone rules change; converting
to UTC too early may use rules that become outdated by the time the
timestamp arrives. The option to convert to UTC will remain, but may not be
default.
* Introduce `parse` to parse as much as it can, but return any of the structs,
`%DateTime{}` `%NaiveDateTime{}` `%Date{}` or `%Time{}`. It would be up to
you to match on what the result is and do what you will. If you know you
want the one specific struct, then you can continue to use the more-specific
functions like `parse_date`.
## Required reading
* [Elixir DateTime docs](https://hexdocs.pm/elixir/DateTime.html)
* [Elixir NaiveDateTime docs](https://hexdocs.pm/elixir/NaiveDateTime.html)
* [Elixir Date docs](https://hexdocs.pm/elixir/Date.html)
* [Elixir Time docs](https://hexdocs.pm/elixir/Time.html)
* [Elixir Calendar docs](https://hexdocs.pm/elixir/Calendar.html)
* [How to save datetimes for future events (when UTC is not the right answer)](http://www.creativedeletion.com/2015/03/19/persisting_future_datetimes.html)
* tldr: rules change, so don't convert to UTC too early. The future might
change the timezone conversion rules.
## Documentation
[Online Documentation](https://hexdocs.pm/date_time_parser)
## Examples
```elixir
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")
{:ok, ~N[2034-01-13 00:00:00]}
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("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, ~U[2018-01-01T15:24:00Z]}
# the ~U is a DateTime sigil introduced in Elixir 1.9.0
iex> DateTimeParser.parse_datetime(~s|"Dec 1, 2018 7:39:53 AM PST"|)
{:ok, ~U[2018-12-01T14:39:53Z]}
# Notice that the date is converted to UTC by default
iex> {:ok, datetime} = DateTimeParser.parse_datetime(~s|"Dec 1, 2018 7:39:53 AM PST"|, to_utc: false)
iex> datetime
#DateTime<2018-12-01 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_datetime(nil)
{:error, "Could not parse nil"}
```
[See more examples automatically generated by the tests](./EXAMPLES.md)
## Installation
Add `date_time_parser` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:date_time_parser, "~> 0.1.4"}
]
end
```
## Changelog
[View Changelog](./CHANGELOG.md)
## Contributing
[How to contribute](./CONTRIBUTING.md)
## Special Thanks
[<img src="https://www.taxjar.com/img/lander/logo.svg" height=75 />](https://www.taxjar.com)