This tutorial gives you examples of how to convert a String to a DateTime
in Dart (also works in Flutter) using DateTime.parse
, HttpDate.pasre
, and DateFormat().parse()
.
Dart uses DateTime
as data type to represent a time instant. Storing a time instant as DateTime
has many advantages compared to storing the data as a String, such as the ability to compare with other time instant and the simplicity to add a certain amount of time to the instant. If you have the value as String and you want to convert it to a DateTime
instance, Dart already provides some methods. Below are the methods that can be used for the conversion, along with explanation and examples for each method.
Using DateTime.parse
DateTime
has a static method parse()
that can be used to parse values with certain formats.
static DateTime parse(String formattedString)
The method can be used by importing package:intl/intl.dart
. It creates a new DateTime
based on the given string. The passed value must not be null. A FormatException
will be thrown if the passed value cannot be parsed.
It supports a subset of ISO 8601 including the subset accepted by RFC 3339. The supported formats consist of up to three parts: date, optional time, and optional time-zone offset. The only required part is date, while the others are optional. That means you can pass date only, date + time, or date + time + time-zone offset. Between date and time needs to be separated using "T" or space.
The date must contain year, month, and day with each unit can be separated with optional dash (-
). The year can have 4 to 6 digits and negative sign (-
) can be added to represent B.C. years. Examples: "2020-01-02" "20200102", "-12345-03-04"
The time part is optional. If present, it consists of 2-digit hour, optional 2-digit minute, optional 2-digit second, and optional dot (.
) or comma (,
) followed by one or more digit second fraction. Between hour, minute, and second can be separated by optional colon (:
). Examples: "07", 0712", "071250", "071250,1111", "07:12:50.222222".
The time-zone offset part is optional. If present, the value can be 'Z' (or 'z') or a 2-digit hour part followed by optional 2-digit minute part separated by optional colon (:
). Examples: "Z", "z", "+07", "+0700", "+07:00". If you pass a non-UTC time-zone, the result will be converted to UTC time.
To use DateTime.parse
, you only need to pass the string you want to convert.
DateTime dt = DateTime.parse('2020-01-02 03:04:05');
print(dt); // 2020-01-02 03:04:05.000
Based on the explanation above, below are some examples of valid inputs along with the outputs.
print(DateTime.parse('2020-01-02')); // 2020-01-02 00:00:00.000
print(DateTime.parse('20200102')); // 2020-01-02 00:00:00.000
print(DateTime.parse('-12345-03-04')); // -12345-03-04 00:00:00.000
print(DateTime.parse('2020-01-02 07')); // 2020-01-02 07:00:00.000
print(DateTime.parse('2020-01-02T07')); // 2020-01-02 07:00:00.000
print(DateTime.parse('2020-01-02T07:12')); // 2020-01-02 07:12:00.000
print(DateTime.parse('2020-01-02T07:12:50')); // 2020-01-02 07:12:50.000
print(DateTime.parse('2020-01-02T07:12:50Z')); // 2020-01-02 07:12:50.000Z
print(DateTime.parse('2020-01-02T07:12:50+07')); // 2020-01-02 00:12:50.000Z
print(DateTime.parse('2020-01-02T07:12:50+0700')); // 2020-01-02 00:12:50.00
print(DateTime.parse('2020-01-02T07:12:50+07:00')); // 2020-01-02 00:12:50.00
What if you pass an invalid value. For example, the passed value below only contains the year without month and day.
print(DateTime.parse('2020'));
Because the passed value is invalid, it will throw FormatException: Invalid date format
.
Besides invalid value, you cannot pass null value.
print(DateTime.parse(null));
The result will be an exception Invalid argument(s) (input): Must not be null
Using DateTime.tryParse
Because DateTime.parse
will throw FormatException
for invalid value, you may need to catch the exception. Dart already provides another static method DateTime.tryParse
. It wraps DateTime.parse
inside a try-catch block. If FormatException
is thrown, it will return null.
static DateTime parse(String formattedString)
Below is an example of using tryParse
with the previous invalid value.
print(DateTime.tryParse('2020')); // null
However, you cannot pass null value as it will throw the same exception as using parse()
.
Using HttpDate.parse
If the given date complies with HTTP date formats according to RFC-1123, RFC-850, or ANSI C's asctime(), you can use HttpDate.parse
.
static DateTime parse(String formattedString)
You need to import dart:io
first to use the method. The formats supported by the method are:
- EEE, dd MMM yyyy HH:mm:ss 'GMT'
- EEEE, dd-MMM-yyyy HH:mm:ss 'GMT'
- EEE MMM dd HH:mm:ss yyyy
Below are some examples that comply with the supported formats.
print(HttpDate.parse("Wed, 28 Oct 2020 01:02:03 GMT")); // 2020-10-28 01:02:03.000Z
print(HttpDate.parse("Wednesday, 28-Oct-2020 01:02:03 GMT")); // 2020-10-28 01:02:03.000Z
print(HttpDate.parse("Wed Oct 28 01:02:03 2020")); // 2020-10-28 01:02:03.000Z
What will happen if you pass an invalid date?
HttpDate.parse("Wed- 2020-Oct-28-01:02:03")
The above example will throw HttpException: Invalid HTTP date Wed- 2020-Oct-28-01:02:03
. Unfortunately, there is no tryParse
method for HttpDate
which means you have to catch the exception yourself. It will also throw an exception if you pass null value.
Using DateFormat
If you need to parse a String whose format is not supported by DateTime.parse
or HttpDate.parse
, you can use DateFormat
and define the pattern of the String you want to parse.
What you need to do is creating a DateFormat
by passing the pattern in the constructor, then call DateFormat
's parse()
instance method by passing the string to be parsed. To use the method, it's required to import intl/intl.dart.
DateTime parse(String inputString, [utc = false])
Below are the characters supported by DateFormat
.
- G: Era designator (text). Examples: AD, BC.
- y: Year (number). Examples: 2020.
- M: Month in year (text & number). Examples: 01 (M/MM), Jan (MMM), January (MMMM).
- L: Standalone month (text & number). Examples: 01 (L/LL), Jan (LLL), January (LLLL).
- d: Day in month (number). Examples: 10.
- c: Standalone day (number). Examples: 10.
- h: Hour in am/pm (1~12) (number). Examples: 12.
- H: Hour in day (0~23) (number). Examples: 0.
- m: Minute in hour (number). Examples: 20.
- s: Second in minute (number). Examples: 30.
- S: Fractional second (number). Examples: 123.
- E: Day of week (text). Examples: Sunday.
- D: Day in year (number). Examples: 200.
- a: am/pm marker (text). Examples: AM, PM.
- k: Hour in day (1~24) (number). Examples: 24.
- K: Hour in am/pm (0~11) (number). Examples: 0.
- z: Time zone (text). Examples: Pacific Standard Time. Not yet implemented.
- Z: Time zone (RFC 822) (number). Examples: +0700. Not yet implemented.
- v: Time zone (generic) (text). Examples: Pacific Time. Not yet implemented.
- Q: quarter (text). Examples: Q1.
- ': Escape for text (delimiter). Examples: 'custom text'.
- ": Single quote (literal). Examples: 'o''clock'.
The symbols above can have multi letters variations to define the expected form. For example, a symbol can have full form, abbreviated form, and numeric form which is distinguished by the number of letters.
Below is the rule for symbols that only supports text presentation.
- < 3 letters: numeric form.
- 3 letters: short/abbreviated form.
- 4 or more letters: full form.
- 5 letters: narrow form for standalone, otherwise not used.
If the symbol is numeric, the number of letters is used to define the number of digits. Though you can use yy
while formatting DateTime
to String for truncating the year into 2 digits, Dart treats 2 digits year in String as the number of years from 0 A.D.. That means 20 is converted to 0020, not 2020.
Beware in using the characters above to define a pattern because Dart hasn't implemented all the characters. The characters related to time zone (z, Z, v) haven't been implemented so far.
Because a DateTime
must contain year, month, day, hour, minute, second, and second fraction, the default value will be set to each unit whose value cannot be obtained from the parsed String. The default value for year is 1970. For month and day, the default value is 1. 0 is the default value for hour, minute, second, and second fraction. Even you can pass an empty string which means every unit is set with default value.
print(new DateFormat('').parse('')); // 1970-01-01 00:00:00.000
print(new DateFormat('MM').parse('02')); // 1970-02-01 00:00:00.000
print(new DateFormat('yyyy').parse('2020')); // 2020-01-01 00:00:00.000
print(new DateFormat('MM/yyyy').parse('01/2020')); // 2020-01-01 00:00:00.000
print(new DateFormat('MMM yyyy').parse('Feb 2020')); // 2020-02-01 00:00:00.000
print(new DateFormat('MMMM yyyy').parse('March 2020')); // 2020-03-01 00:00:00.000
print(new DateFormat('yyyy/MM/dd').parse('2020/04/03')); // 2020-04-03 00:00:00.000
print(new DateFormat('yyyy/MM/dd HH:mm:ss').parse('2020/04/03 17:03:02')); // 2020-04-03 17:03:02.000
print(new DateFormat('EEEE dd MMMM yyyy HH:mm:ss \'GMT\'').parse('Wednesday 28 October 2020 01:02:03 GMT')); // 2020-10-28 01:02:03.000
print(new DateFormat('EEE d/LLLL/yyyy hh:mm:ss G').parse('Wed 10/January/2020 15:02:03 BC')); // 2020-01-10 15:02:03.000
print(new DateFormat('yyyyy.MMMM.dd GGG hh:mm aaa').parse('02020.July.10 AD 11:09 PM')); // 2020-07-10 23:09:00.000
Passing a value that cannot be parsed (either invalid or null) like the examples below will cause the method to throw FormatException
.
print(new DateFormat('yyyy/MM/dd').parse('x'));
print(new DateFormat('yyyy/MM/dd').parse(null));
That's how to parse a String to a DateTime
in Dart. For basic formats, it should be quite easy to perform the conversion. However, there are still some limitations such as the lack of time zone support which requires a workaround for now.
You can also read about: