This tutorial shows various ways to convert a DateTime
instance to a string with a specific format, including localization support.
In Dart, values that represent a time instance are usually stored as a DateTime
variable. DateTime
has a toString
method that returns a human-readable string. However, in most cases, there is a requirement to display the value in a particular format. This tutorial explains several ways to convert a DateTime
to a string with any format you want.
First of all, we need to create a DateTime
instance.
DateTime dt = DateTime.now();
In the examples below, we are going to format the instance above.
Format to ISO-8601
ISO-8601 defines standards for date time formats. Flutter has built-in functionality to convert a DateTime
to a string that complies with the ISO-8601 full-precision extended format. For UTC time, the format is yyyy-MM-ddTHH:mm:ss.mmmuuuZ
. For non-UTC time, the format is yyyy-MM-ddTHH:mm:ss.mmmuuu
(without Z
). To return a string with that format, just call the toIso8601String
method.
final nonUtcIso8601 = dt.toIso8601String();
final utcIso8601 = dt.toUtc().toIso8601String();
print('Non UTC: $nonUtcIso8601');
print('UTC: $utcIso8601');
Output:
Non UTC: 2023-06-01T17:15:55.469427
UTC: 2023-06-01T10:15:55.469427Z
Without Library
The DateTime
class has properties for accessing the components of a date time. You can access some of the properties to be included in the formatted string. Below are the important properties that you may need to use.
year
month
day
hour
minute
second
millisecond
microsecond
weekday
timeZoneName
timeZoneOffset
Example:
final result = '${dt.year}-${dt.month}-${dt.day} (${dt.hour}:${dt.minute}:${dt.second}})';
print(result);
Output:
2023-06-01 (17:15:55)
Using intl
Package
Formatting a date can be a challenging thing if your application needs to display various date formats. You may need to write the code and perform testing for each format. That requires a lot of effort. In addition, if your application supports multiple languages, formatting to specific language(s) or locales(s) needs additional effort as well. That's because parts of the formatted string can have locale-specific values. For example, the list of month names in English is different to other languages such as French, German, Spanish, or Indonesian. Fortunately, there is an official package from dart.dev
that allows you to convert a DateTime
to any format using various locales.
intl
is a popular library that provides internationalization and localization. It has a class named DateFormat
which can be used for formatting and parsing date time values.
First, add it to the dependencies
of your pubspec.yaml
.
dependencies:
intl: ^0.18.1
Then, run dart pub get
(or flutter pub get
for Flutter) to install the package. After that, add the import statement below on the file where you want to use it.
import 'package:intl/intl.dart';
Next, you need to create a DateFormat
instance and call the format
method by passing the DateTime
to be formatted. The DateFormat
instance defines the pattern to be used. You can create it using one of the named constructors if the pattern you want to use is already defined. The list of predefined patterns can be seen on the class documentation. Below is the usage example.
final result = DateFormat('yMMMMEEEEd').format(DateTime.now();
print(result):
Output:
Thursday, June 1, 2023
As of version 0.18.1, here is the list of the predefined patterns along with the example.
d
(1)E
(Thu)EEEE
(Thursday)LLL
(Jun)LLLL
(June)M
(6)Md
(6/1)MEd
(Thu, 6/1)MMM
(Jun)MMMd
(Jun 1)MMMEd
(Thu, Jun 1)MMMM
(June)MMMMd
(June 1)MMMMEEEEd
(Thursday, June 1)QQQ
(Q2)QQQQ
(2nd quarter)y
(2023)yM
(6/2023)yMd
(6/1/2023)yMEd
(Thu, 6/1/2023)yMMM
(Jun 2023)yMMMd
(Jun 1, 2023)yMMMEd
(Thu, Jun 1, 2023)yMMMM
(June 2023)yMMMMd
(June 1, 2023)yMMMMEEEEd
(Thursday, June 1, 2023)yQQQ
(Q2 2023)yQQQQ
(2nd quarter 2023)H
(16)Hm
(16:38)Hms
(16:38:40)j
(4 PM)jm
(4:38 PM)jms
(4:38:40 PM)d
(1)E
(Thu)EEEE
(Thursday)LLL
(Jun)LLLL
(June)M
(6)Md
(6/1)MEd
(Thu, 6/1)MMM
(Jun)MMMd
(Jun 1)MMMEd
(Thu, Jun 1)MMMM
(June)MMMMd
(June 1)MMMMEEEEd
(Thursday, June 1)QQQ
(Q2)QQQQ
(2nd quarter)y
(2023)yM
(6/2023)yMd
(6/1/2023)yMEd
(Thu, 6/1/2023)yMMM
(Jun 2023)yMMMd
(Jun 1, 2023)yMMMEd
(Thu, Jun 1, 2023)yMMMM
(June 2023)yMMMMd
(June 1, 2023)yMMMMEEEEd
(Thursday, June 1, 2023)yQQQ
(Q2 2023)yQQQQ
(2nd quarter 2023)H
(16)Hm
(16:38)Hms
(16:38:40)j
(4 PM)jm
(4:38 PM)jms
(4:38:40 PM)
If the format you want to use is not already defined, you can create a DateFormat
instance with a custom pattern.
print(DateFormat('yyyy-MM-dd').format(currentTime));
Below is the list of characters that can be processed as a part of the pattern:
G
(era designator, e.g. AD)y
(year, e.g. 1996)M
(month in year, e.g. July & 07)L
(standalone month, e.g. July & 07)d
(day in month, e.g. 10)c
(standalone day, e.g. 10)h
(hour in am/pm (1~12), e.g. 12)H
(hour in day (0~23), e.g. 0)m
(minute in hour, e.g. 30)s
(second in minute, e.g. 55)S
(fractional second, e.g. 978)E
(day of week, e.g. Tuesday)D
(day in year, e.g. 189)a
(am/pm marker, e.g. PM)k
(hour in day (1~24), e.g. 24)K
(hour in am/pm (0~11), e.g. 0)Q
(quarter, e.g. Q3)'
(escape for text, e.g. 'Date=')''
(single quote, e.g. o''clock')
intl
Localization
The intl
package supports localization. The default locale is en_US
. To use another locale, you need to call intl
's initializeDateFormatting
method. The method is responsible for loading date symbols for all supported locales and the date pattern map. It's an asynchronous method that returns Future
, so you have to call it using await inside an async block.
await initializeDateFormatting();
Alternatively, you can chain the Future
.
initializeDateFormatting()
.then((_) {
// your code here
});
To run a function with a specific locale. you can use Intl.withLocale
by passing the locale as the first argument and the function to be run as the second argument. In the example below, the first call to formatDateTime
uses id_ID as the locale, while the second call uses pt_BR as the locale.
Intl.withLocale("id_ID", () {
final result = DateFormat.yMEd().format(dt);
print('id_ID: $result');
});
Intl.withLocale("pt_BR", () {
final result = DateFormat.yMEd().format(dt);
print('pt_BR: $result');
});
Output:
Kam, 1/6/2023
qui., 01/06/2023
It's also possible to change the default locale.
Intl.defaultLocale = "id_ID";
Using jiffy
Package
Jiffy is a date time package for Dart inspired by momentjs for Javascript. It also supports formatting date time with various patterns. To use the package, add it to the dependencies
of your pubspec.yaml
file and run dart pub get
(or flutter pub get
for Flutter)
dependencies:
jiffy: ^6.1.0
Then, import the library on the file where you want to use it
import 'package:jiffy/jiffy.dart';
To work with Jiffy, you need to have the time instant as a Jiffy
instance. If you already have a DateTime
instance, you can convert it to a Jiffy
instance using Jiffy.parseFromDateTime
factory constructor.
final currentTime = DateTime.now();
final jdt = Jiffy.parseFromDateTime(currentTime);
Jiffy has some predefined getters for common patterns. To format a Jiffy
instance to a string, just access the getter with the pattern you want to use.
final result = jdt.MMMMEEEEd;
print(result);
Output:
Thursday, June 1
Below is the list of predefined getters along with the example.
E
(Thu)EEEE
(Thursday)Md
(6/1)MEd
(Thu, 6/1)MMM
(Jun)MMMd
(Jun 1)MMMEd
(Thu, Jun 1)MMMM
(June)MMMMd
(June 1)MMMMEEEEd
(Thursday, June 1)QQQ
(Q2)QQQQ
(2nd quarter)yM
(6/2023)yMd
(6/1/2023)yMEd
(Thu, 6/1/2023)yMMM
(Jun 2023)yMMMd
(Jun 1, 2023)yMMMdjm
(Jun 1, 2023 6:10 PM)yMMMEd
(Thu, Jun 1, 2023)yMMMEdjm
(Thu, Jun 1, 2023 6:10 PM)yMMMM
(June 2023)yMMMMd
(June 1, 2023)yMMMMdjm
(June 1, 2023 6:10 PM)yMMMMEEEEd
(Thursday, June 1, 2023)yMMMMEEEEdjm
(Thursday, June 1, 2023 6:10 PM)yQQQ
(Q2 2023)yQQQQ
(2nd quarter 2023)H
(18)Hm
(18:10)Hms
(18:10:37)j
(6 PM)jm
(6:10 PM)jms
(6:10:37 PM)
It's also possible to use a custom pattern. The list of supported characters for pattern is basically the same as the DateFormat
class of intl
package, since Jiffy runs on top of DateFormat
.
Jiffy.parseFromDateTime(currentTime).format(pattern: 'yyyy-MM-dd') // 2023-06-01
jiffy
Localization
Jiffy also supports localization. To use a particular locale, call Jiffy.setLocale
method and pass the locale you want to use. It returns a Future
, so you have to use await
inside an async
block or chain the Future
. To switch to another locale, call the setLocale
method again. You can see the package documentation for the list of supported locales.
await Jiffy.setLocale('id');
final idResult = DateFormat('yyyy, MMMM dd').format(currentTime);
print('id: $idResult');
await Jiffy.setLocale('fr_ca');
final frCaResult = DateFormat('yyyy, MMMM dd').format(currentTime);
print('fr_ca: $frCaResult');
Output:
id: 2023, Juni 01
fr_ca: 2023, juin 01
Summary
There are several ways to format a DateTime
in Dart. If the expected output is in ISO-8601 format, just use the toIso8601String
method. If the format is simple and you don't need to handle various formats or localization, writing your own code can be a lightweight solution as you don't need any additional library. If you get a requirement to handle multiple or complex formats, especially with localization support, using an additional library such as intl
or jiffy
can be the solution.
You can also read about: