Skip to content

Commit f5ed29e

Browse files
committed
Support [day of week] [nth] [month name] [year] format
This adds support for dates formatted like: - Sunday 5th Jan 2025 - Tuesday 2nd Feburary 2024 - 1st January 2025
1 parent 83d6021 commit f5ed29e

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

EXAMPLES.livemd

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,23 @@ convert to UTC or to assume a time when not present.
192192
|`10:13.7`|`10:13:00`|parse_time| |
193193
|`11 July 2017 1:43:46 PM`|`2017-07-11`|parse_date| |
194194
|`11 July 2017 1:43:46 PM`|`2017-07-11T13:43:46`|parse_datetime| |
195+
|`11th July 2017 1:43:46 PM`|`2017-07-11T13:43:46`|parse_datetime| |
195196
|`12/5`|`2021-12-05`|parse_date|`[assume_date: ~D[2021-01-01]]`|
196197
|`12:30PM`|`12:30:00`|parse_time|`[assume_date: ~D[2020-01-01]]`|
197198
|`12:30PM`|`2020-01-01T12:30:00`|parse|`[assume_date: ~D[2020-01-01]]`|
199+
|`12th August 2018 08:15:22`|`2018-08-12T08:15:22`|parse_datetime| |
198200
|`13/5`|`2021-05-13`|parse_date|`[assume_date: ~D[2021-01-01]]`|
201+
|`13th Sep 2019 9:00 AM`|`2019-09-13T09:00:00`|parse_datetime| |
202+
|`14-Jul-2023`|`2023-07-14T00:00:00`|parse_datetime|`[assume_time: true]`|
199203
|`18-07-2018 20:38:34 +00:00`|`2018-07-18T20:38:34Z`|parse| |
200204
|`18-12-29`|`2018-12-29`|parse| |
201205
|`19 September 18 2:33:08 PM`|`2018-09-19`|parse_date| |
202206
|`19 September 18 2:33:08 PM`|`2018-09-19T14:33:08`|parse_datetime| |
203207
|`19 September 2018 08:15:22 AM`|`2018-09-19`|parse_date| |
204208
|`19 September 2018 08:15:22 AM`|`2018-09-19T08:15:22`|parse_datetime| |
205209
|`19-Dec-19`|`2019-12-19`|parse| |
210+
|`1st January 2025`|`2025-01-01`|parse_date| |
211+
|`1st January 2025 09:15:30`|`2025-01-01T09:15:30`|parse_datetime| |
206212
|`2`|`1900-01-01`|parse_date| |
207213
|`2.0`|`1900-01-01T00:00:00`|parse_datetime| |
208214
|`2/5`|`2021-02-05`|parse_date|`[assume_date: ~D[2021-01-01]]`|
@@ -271,27 +277,40 @@ convert to UTC or to assume a time when not present.
271277
|`2034-1-9`|`2034-01-09`|parse_date| |
272278
|`2034-1-9`|`2034-01-09T00:00:00`|parse_datetime|`[assume_time: true]`|
273279
|`20340109`|`2034-01-09T00:00:00`|parse_datetime|`[assume_time: true]`|
280+
|`21st April 2022`|`2022-04-21`|parse_date| |
281+
|`21st April 2022`|`2022-04-21T00:00:00`|parse_datetime|`[assume_time: true]`|
282+
|`22nd May 2021`|`2021-05-22`|parse_date| |
283+
|`22nd May 2021 12:00 PM`|`2021-05-22T12:00:00`|parse_datetime| |
274284
|`23-05-2019 @ 10:01`|`2019-05-23`|parse_date| |
275285
|`23-05-2019 @ 10:01`|`2019-05-23T10:01:00`|parse_datetime|`[assume_time: true]`|
286+
|`23rd June 2020`|`2020-06-23`|parse_date| |
276287
|`24:00`|`Could not parse "24:00"`|parse_time| |
288+
|`25th November 2017`|`2017-11-25`|parse_date| |
277289
|`29/Aug./2018`|`2018-08-29`|parse| |
278290
|`29/Sep./2018`|`2018-09-29`|parse| |
291+
|`2nd February 2024`|`2024-02-02`|parse_date| |
279292
|`30134`|`1982-07-02`|parse| |
280293
|`30134.0`|`1982-07-02T00:00:00`|parse| |
294+
|`30th Sept 2016`|`2016-09-30`|parse_date| |
295+
|`31st Dec 2019`|`2019-12-31`|parse_date| |
281296
|`34-1-13`|`2034-01-13`|parse_date| |
282297
|`34-1-13`|`2034-01-13T00:00:00`|parse_datetime|`[assume_time: true]`|
298+
|`3rd March 2023`|`2023-03-03`|parse_date| |
283299
|`4/24/2019 0:00:00`|`2019-04-24`|parse_date| |
284300
|`4/24/2019 0:00:00`|`2019-04-24T00:00:00`|parse_datetime| |
285301
|`41261.6013888889`|`2012-12-18`|parse_date| |
286302
|`41261.6013888889`|`14:26:00`|parse_time| |
287303
|`41261.6013888889`|`2012-12-18T14:26:00`|parse_datetime| |
304+
|`4th Oct 2018`|`2018-10-04`|parse_date| |
288305
|`5/12/2019 12:21:58 PM`|`2019-05-12T12:21:58`|parse| |
289306
|`5/2/2019 0:00:00`|`2019-05-02`|parse_date| |
290307
|`5/2/2019 0:00:00`|`2019-05-02T00:00:00`|parse_datetime| |
291308
|`5/2/2019 12:00:00 AM`|`2019-05-02`|parse_date| |
292309
|`5/2/2019 12:00:00 AM`|`2019-05-02T00:00:00`|parse_datetime| |
293310
|`5/31/2019 12:00:00 AM`|`2019-05-31`|parse_date| |
294311
|`5/31/2019 12:00:00 AM`|`2019-05-31T00:00:00`|parse_datetime| |
312+
|`5th Jan 2025`|`2025-01-05`|parse_date| |
313+
|`5th Jan 2025 10:30:00 AM`|`2025-01-05T10:30:00`|parse_datetime| |
295314
|`62`|`1900-03-02`|parse_date| |
296315
|`62`|`1900-03-02T00:00:00`|parse|`[assume_time: true]`|
297316
|`62`|`1904-03-03T00:00:00`|parse|`[assume_time: true, use_1904_date_system: true]`|
@@ -342,6 +361,7 @@ convert to UTC or to assume a time when not present.
342361
|`Fri Mar 2 09:01:57 2018`|`2018-03-02T09:01:57`|parse| |
343362
|`Fri Mar 31 2017 21:41:40 GMT+0000 (UTC)`|`2017-03-31T21:41:40Z`|parse| |
344363
|`Friday 02 February 2018 10:42:21 AM`|`2018-02-02T10:42:21`|parse| |
364+
|`Friday 22nd May 2021`|`2021-05-22`|parse_date| |
345365
|`Jan 2020`|`2020-01-01`|parse_date|`[assume_date: ~D[0001-12-01]]`|
346366
|`Jan-01-19`|`2019-01-01`|parse| |
347367
|`Jan-01-19`|`2019-01-01T00:00:00`|parse|`[assume_time: true]`|
@@ -352,15 +372,19 @@ convert to UTC or to assume a time when not present.
352372
|`May 30, 2019 4:31:09 AM PDT`|`2019-05-30T11:31:09Z`|parse_datetime|`[to_utc: true]`|
353373
|`Monday 01 October 2018 06:34:19 AM`|`2018-10-01T06:34:19`|parse| |
354374
|`Monday 02 October 2017 9:04:49 AM`|`2017-10-02T09:04:49`|parse| |
375+
|`Monday 1st January 2025`|`2025-01-01`|parse_date| |
376+
|`Monday 1st January 2025 09:15:30`|`2025-01-01T09:15:30`|parse_datetime| |
355377
|`November 29, 2016`|`2016-11-29`|parse_date| |
356378
|`November 29, 2016`|`2016-11-29T00:00:00`|parse_datetime|`[assume_time: true]`|
357379
|`Oct 5, 2018 6:16:56 PM PDT`|`2018-10-05`|parse_date| |
358380
|`Oct 5, 2018 6:16:56 PM PDT`|`2018-10-06T01:16:56Z`|parse_datetime|`[to_utc: true]`|
359381
|`October 1995`|`1995-10-01`|parse_date|`[assume_date: ~D[0001-12-01]]`|
382+
|`Saturday 23rd June 2020`|`2020-06-23`|parse_date| |
360383
|`Sep-19-16`|`2016-09-19`|parse_date| |
361384
|`Sep-19-16`|`2016-09-19T00:00:00`|parse_datetime|`[assume_time: true]`|
362385
|`Sun 01 January 2017 10:11:02 PM`|`2017-01-01`|parse_date| |
363386
|`Sun 01 January 2017 10:11:02 PM`|`2017-01-01T22:11:02`|parse_datetime| |
387+
|`Sun 31st Dec 2019`|`2019-12-31`|parse_date| |
364388
|`Sun Jan 08 2017 04:28:42 GMT+0000 (UTC)`|`2017-01-08T04:28:42Z`|parse| |
365389
|`Sun Jul 1 00:31:18 2018`|`2018-07-01T00:31:18`|parse| |
366390
|`Sun, 01 January 2017 10:11:02 PM`|`2017-01-01`|parse_date| |
@@ -369,12 +393,19 @@ convert to UTC or to assume a time when not present.
369393
|`Sunday 01 January 2017 10:11:02 PM`|`2017-01-01`|parse_date| |
370394
|`Sunday 01 January 2017 10:11:02 PM`|`2017-01-01T22:11:02`|parse_datetime| |
371395
|`Sunday 01 January 2017 10:11:02 PM`|`2017-01-01T22:11:02`|parse| |
396+
|`Sunday 5th Jan 2025`|`2025-01-05`|parse_date| |
397+
|`Sunday 5th Jan 2025 10:30:00 AM`|`2025-01-05T10:30:00`|parse_datetime| |
372398
|`Sunday, 01 January 2017 10:11:02 PM`|`2017-01-01`|parse_date| |
373399
|`Sunday, 01 January 2017 10:11:02 PM`|`2017-01-01T22:11:02`|parse_datetime| |
374400
|`Thu Aug 09 2018 17:13:43 GMT+0000 (UTC)`|`2018-08-09T17:13:43Z`|parse| |
375401
|`Thu Feb 08 00:24:33 2018`|`2018-02-08T00:24:33`|parse| |
376402
|`Thu Jul 5 12:19:56 2018`|`2018-07-05T12:19:56`|parse| |
403+
|`Thursday 21st April 2022`|`2022-04-21`|parse_date| |
377404
|`Thursday 30 August 2018 11:31:18 AM`|`2018-08-30T11:31:18`|parse| |
378405
|`Tue Jul 31 06:44:39 2018`|`2018-07-31T06:44:39`|parse| |
379406
|`Tuesday 11 July 2017 1:43:46 PM`|`2017-07-11T13:43:46`|parse| |
407+
|`Tuesday 2nd February 2024`|`2024-02-02`|parse_date| |
408+
|`Tuesday 2nd February 2024 14:20:00`|`2024-02-02T14:20:00`|parse_datetime| |
409+
|`Wednesday 3rd March 2023`|`2023-03-03`|parse_date| |
410+
|`Wednesday 3rd March 2023 3:45 PM`|`2023-03-03T15:45:00`|parse_datetime| |
380411
|`jul-10-18`|`2018-07-10`|parse| |

lib/combinators.ex.exs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,13 @@ defmodule DateTimeParser.Combinators do
241241
|> unwrap_and_tag(:month)
242242
|> label("numeric month from 01-12")
243243

244+
ordinal_suffix =
245+
~w(st nd rd th)
246+
|> Enum.map(&string/1)
247+
|> choice()
248+
|> ignore()
249+
|> label("ordinal suffix (st, nd, rd, th)")
250+
244251
day2 =
245252
(~w(01 02 03 04 05 06 07 08 09) ++ Enum.map(10..31, &to_string/1))
246253
|> Enum.map(&string/1)
@@ -255,6 +262,7 @@ defmodule DateTimeParser.Combinators do
255262

256263
day =
257264
choice([day2, day1])
265+
|> concat(ordinal_suffix |> optional())
258266
|> map(:to_integer)
259267
|> unwrap_and_tag(:day)
260268
|> label("numeric day from 01-31")

test/date_time_parser_test.exs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ defmodule DateTimeParserTest do
392392
describe "parse_datetime/1 - DMY" do
393393
test_datetime_parsing("23-05-2019 @ 10:01", ~N[2019-05-23 10:01:00], assume_time: true)
394394
test_datetime_parsing("9-Feb-18", ~N[2018-02-09 00:00:00], assume_time: true)
395+
test_datetime_parsing("14-Jul-2023", ~N[2023-07-14 00:00:00], assume_time: true)
395396
test_datetime_parsing("9-2-32", ~N[2032-02-09 00:00:00], assume_time: true)
396397
end
397398

@@ -582,6 +583,20 @@ defmodule DateTimeParserTest do
582583
test_datetime_parsing("11 July 2017 1:43:46 PM", ~N[2017-07-11 13:43:46])
583584
end
584585

586+
describe "parse_datetime/1 - ordinal suffixes" do
587+
test_datetime_parsing("Sunday 5th Jan 2025 10:30:00 AM", ~N[2025-01-05 10:30:00])
588+
test_datetime_parsing("Monday 1st January 2025 09:15:30", ~N[2025-01-01 09:15:30])
589+
test_datetime_parsing("Tuesday 2nd February 2024 14:20:00", ~N[2024-02-02 14:20:00])
590+
test_datetime_parsing("Wednesday 3rd March 2023 3:45 PM", ~N[2023-03-03 15:45:00])
591+
test_datetime_parsing("5th Jan 2025 10:30:00 AM", ~N[2025-01-05 10:30:00])
592+
test_datetime_parsing("1st January 2025 09:15:30", ~N[2025-01-01 09:15:30])
593+
test_datetime_parsing("21st April 2022", ~N[2022-04-21 00:00:00], assume_time: true)
594+
test_datetime_parsing("22nd May 2021 12:00 PM", ~N[2021-05-22 12:00:00])
595+
test_datetime_parsing("11th July 2017 1:43:46 PM", ~N[2017-07-11 13:43:46])
596+
test_datetime_parsing("12th August 2018 08:15:22", ~N[2018-08-12 08:15:22])
597+
test_datetime_parsing("13th Sep 2019 9:00 AM", ~N[2019-09-13 09:00:00])
598+
end
599+
585600
describe "parse_date/1 - vocal" do
586601
test_date_parsing("Sunday 01 January 2017 10:11:02 PM", ~D[2017-01-01])
587602
test_date_parsing("Sunday, 01 January 2017 10:11:02 PM", ~D[2017-01-01])
@@ -596,6 +611,28 @@ defmodule DateTimeParserTest do
596611
test_date_parsing("11 July 2017 1:43:46 PM", ~D[2017-07-11])
597612
end
598613

614+
describe "parse_date/1 - ordinal suffixes" do
615+
test_date_parsing("Sunday 5th Jan 2025", ~D[2025-01-05])
616+
test_date_parsing("Monday 1st January 2025", ~D[2025-01-01])
617+
test_date_parsing("Tuesday 2nd February 2024", ~D[2024-02-02])
618+
test_date_parsing("Wednesday 3rd March 2023", ~D[2023-03-03])
619+
test_date_parsing("Thursday 21st April 2022", ~D[2022-04-21])
620+
test_date_parsing("Friday 22nd May 2021", ~D[2021-05-22])
621+
test_date_parsing("Saturday 23rd June 2020", ~D[2020-06-23])
622+
test_date_parsing("Sun 31st Dec 2019", ~D[2019-12-31])
623+
test_date_parsing("5th Jan 2025", ~D[2025-01-05])
624+
test_date_parsing("1st January 2025", ~D[2025-01-01])
625+
test_date_parsing("2nd February 2024", ~D[2024-02-02])
626+
test_date_parsing("3rd March 2023", ~D[2023-03-03])
627+
test_date_parsing("21st April 2022", ~D[2022-04-21])
628+
test_date_parsing("22nd May 2021", ~D[2021-05-22])
629+
test_date_parsing("23rd June 2020", ~D[2020-06-23])
630+
test_date_parsing("31st Dec 2019", ~D[2019-12-31])
631+
test_date_parsing("4th Oct 2018", ~D[2018-10-04])
632+
test_date_parsing("25th November 2017", ~D[2017-11-25])
633+
test_date_parsing("30th Sept 2016", ~D[2016-09-30])
634+
end
635+
599636
describe "parse_date/1 - epoch" do
600637
test_date_parsing("99999999999", ~D[5138-11-16])
601638
test_date_parsing("9999999999", ~D[2286-11-20])

0 commit comments

Comments
 (0)