parse

This function offers a generic date/time string Parser which is able to parse most known formats to represent a date and/or time.

This function attempts to be forgiving with regards to unlikely input formats, returning a SysTime object even for dates which are ambiguous.

If an element of a date/time stamp is omitted, the following rules are applied:

  • If AM or PM is left unspecified, a 24-hour clock is assumed, however, an hour on a 12-hour clock (0 <= hour <= 12) *must* be specified if AM or PM is specified.
  • If a time zone is omitted, a SysTime is given with the timezone of the host machine.

Missing information is allowed, and what ever is given is applied on top of the defaultDate parameter, which defaults to January 1, 1 AD at midnight. E.g. a string of "10:00 AM" with a defaultDate of SysTime(Date(2016, 1, 1)) will yield SysTime(DateTime(2016, 1, 1, 10, 0, 0)).

If your date string uses timezone names in place of UTC offsets, then timezone information must be user provided, as there is no way to reliably get timezones from the OS by abbreviation. But, the timezone will be properly set if an offset is given. Timezone info and their abbreviations change constantly, so it's a good idea to not rely on timezoneInfos too much.

This function allocates memory and throws on the GC. In order to reduce GC allocations, use a custom Parser instance with a different allocator.

More...
SysTime
parse
(
Range
)
(
,
Flag!"ignoreTimezone" ignoreTimezone = No.ignoreTimezone
,
const(TimeZone)[string] timezoneInfos = null
,
Flag!"dayFirst" dayFirst = No.dayFirst
,
Flag!"yearFirst" yearFirst = No.yearFirst
,
Flag!"fuzzy" fuzzy = No.fuzzy
,
SysTime defaultDate = SysTime(DateTime(1, 1, 1))
)
if (
isForwardRange!Range &&
!isInfinite!Range
&&
isSomeChar!(ElementEncodingType!Range)
)

Parameters

timeString
Type: Range

A forward range containing a date/time stamp.

ignoreTimezone
Type: Flag!"ignoreTimezone"

Set to false by default, time zones in parsed strings are ignored and a SysTime with the local time zone is returned. If timezone information is not important, setting this to true is slightly faster.

timezoneInfos
Type: const(TimeZone)[string]

Time zone names / aliases which may be present in the string. This argument maps time zone names (and optionally offsets from those time zones) to time zones. This parameter is ignored if ignoreTimezone is set.

dayFirst
Type: Flag!"dayFirst"

Whether to interpret the first value in an ambiguous 3-integer date (e.g. 01/05/09) as the day (true) or month (false). If yearFirst is set to true, this distinguishes between YDM and YMD.

yearFirst
Type: Flag!"yearFirst"

Whether to interpret the first value in an ambiguous 3-integer date (e.g. 01/05/09) as the year. If true, the first number is taken to be the year, otherwise the last number is taken to be the year.

fuzzy
Type: Flag!"fuzzy"

Whether to allow fuzzy parsing, allowing for string like "Today is January 1, 2047 at 8:21:00AM".

defaultDate
Type: SysTime

The date to apply the given information on top of. Defaults to January 1st, 1 AD

Return Value

Type: SysTime

A SysTime object representing the parsed string

Detailed Description

Unicode Specifics

  1. The AA key comparisons done with ParserInfo are on a code unit by code unit basis. As such, if user data passed to this function has a different normalization than the AAs in the used ParserInfo class, then you will get parser exceptions.
  2. While other languages have writing systems without Arabic numerals, the overwhelming majority of dates are written with them. As such, this function does not work with other number systems and expects ASCII numbers.

Throws

ConvException will be thrown for invalid string or unknown string format

TimeException if the date string is successfully parsed but the created date would be invalid

ConvOverflowException if one of the numbers in the parsed date exceeds float.max

Examples

1 immutable brazilTime = new SimpleTimeZone(dur!"seconds"(-10_800));
2 const(TimeZone)[string] timezones = ["BRST" : brazilTime];
3 
4 immutable parsed = parse("Thu Sep 25 10:36:28 BRST 2003", No.ignoreTimezone, timezones);
5 // SysTime opEquals ignores timezones
6 assert(parsed == SysTime(DateTime(2003, 9, 25, 10, 36, 28)));
7 assert(parsed.timezone == brazilTime);
8 
9 assert(parse(
10     "2003 10:36:28 BRST 25 Sep Thu",
11     No.ignoreTimezone,
12     timezones
13 ) == SysTime(DateTime(2003, 9, 25, 10, 36, 28)));
14 assert(parse("Thu Sep 25 10:36:28") == SysTime(DateTime(1, 9, 25, 10, 36, 28)));
15 assert(parse("20030925T104941") == SysTime(DateTime(2003, 9, 25, 10, 49, 41)));
16 assert(parse("2003-09-25T10:49:41") == SysTime(DateTime(2003, 9, 25, 10, 49, 41)));
17 assert(parse("10:36:28") == SysTime(DateTime(1, 1, 1, 10, 36, 28)));
18 assert(parse("09-25-2003") == SysTime(DateTime(2003, 9, 25)));

Apply information on top of defaultDate

1 assert("10:36:28".parse(No.ignoreTimezone, null, No.dayFirst, No.yearFirst,
2     No.fuzzy, SysTime(DateTime(2016, 3, 15)))
3 == SysTime(DateTime(2016, 3, 15, 10, 36, 28)));
4 assert("August 07".parse(No.ignoreTimezone, null, No.dayFirst, No.yearFirst,
5     No.fuzzy, SysTime(DateTime(2016, 1, 1)))
6 == SysTime(Date(2016, 8, 7)));
7 assert("2000".parse(No.ignoreTimezone, null, No.dayFirst, No.yearFirst,
8     No.fuzzy, SysTime(DateTime(2016, 3, 1)))
9 == SysTime(Date(2000, 3, 1)));

Custom allocators

1 import std.experimental.allocator.mallocator : Mallocator;
2 
3 auto customParser = new Parser!Mallocator(new ParserInfo());
4 assert(customParser.parse("2003-09-25T10:49:41") ==
5     SysTime(DateTime(2003, 9, 25, 10, 49, 41)));

Exceptions

1 import std.exception : assertThrown;
2 import std.conv : ConvException;
3 
4 assertThrown!ConvException(parse(""));
5 assertThrown!ConvException(parse("AM"));
6 assertThrown!ConvException(parse("The quick brown fox jumps over the lazy dog"));
7 assertThrown!TimeException(parse("Feb 30, 2007"));
8 assertThrown!TimeException(parse("Jan 20, 2015 PM"));
9 assertThrown!ConvException(parse("01-Jane-01"));
10 assertThrown!ConvException(parse("13:44 AM"));
11 assertThrown!ConvException(parse("January 25, 1921 23:13 PM"));

Custom parser info allows for international time representation

1 import std.utf : byChar;
2 
3 class RusParserInfo : ParserInfo
4 {
5     this()
6     {
7         monthsAA = ParserInfo.convert([
8             ["янв", "Январь"],
9             ["фев", "Февраль"],
10             ["мар", "Март"],
11             ["апр", "Апрель"],
12             ["май", "Май"],
13             ["июн", "Июнь"],
14             ["июл", "Июль"],
15             ["авг", "Август"],
16             ["сен", "Сентябрь"],
17             ["окт", "Октябрь"],
18             ["ноя", "Ноябрь"],
19             ["дек", "Декабрь"]
20         ]);
21     }
22 }
23 
24 auto rusParser = new Parser!GCAllocator(new RusParserInfo());
25 immutable parsedTime = rusParser.parse("10 Сентябрь 2015 10:20");
26 assert(parsedTime == SysTime(DateTime(2015, 9, 10, 10, 20)));
27 
28 immutable parsedTime2 = rusParser.parse("10 Сентябрь 2015 10:20"d.byChar);
29 assert(parsedTime2 == SysTime(DateTime(2015, 9, 10, 10, 20)));

Meta