What is "simpledateformat"
SimpleDateFormat
is a Java class used for formatting and Parsing of dates and times. Therefore, it can convert String
's to java.util.Date
and vice versa.
Its most basic use is to determine the format to be used and pass it in the constructor. For example, to use the format "day/month/year":
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String dataFormatada = sdf.format(new Date());
System.out.println(dataFormatada);
The result will be something like 03/04/2019
(the above code uses the current date, then the output will change as you run the code). The parameter passed in the constructor ("dd/MM/yyyy"
) is what defines the format to be used. In this case, dd
represents the day with two digits (so day 3 will be printed as 03
, for example), MM
represents the month with two digits, and yyyy
represents the year with four digits. The bars have no special meaning - do not correspond to any specific field of the date - and so are interpreted as the character itself /
.
It is important to note that upper and lower case letters make a difference. For example, M
is used for the month, and m
for the minutes. So, DD/mm/YYYY
and dd/MM/yyyy
produce different results:
Date date = new Date(1546214400000L);
TimeZone.setDefault(TimeZone.getTimeZone("America/Sao_Paulo"));
System.out.println(new SimpleDateFormat("dd/MM/yyyy").format(date)); // 30/12/2018
System.out.println(new SimpleDateFormat("DD/mm/YYYY").format(date)); // 364/00/2019
Another detail is that SimpleDateFormat
uses the Timezone default JVM to get the date and time values. This is because java.util.Date
actually represents a timestamp, not a specific date and time. Example:
Date date = new Date(1554319700000L);
TimeZone.setDefault(TimeZone.getTimeZone("America/Sao_Paulo"));
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
System.out.println(sdf.format(date)); // 03/04/2019
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
sdf = new SimpleDateFormat("dd/MM/yyyy");
System.out.println(sdf.format(date)); // 04/04/2019
The builder of SimpleDateFormat
always consider Timezone default that is set in the moment, and so the same Date
can give different results while being formatted. In the example above, when Timezone default is America/Sao_Paulo
(which corresponds to the Official Time of Brasilia), the result is April 3, but when the Timezone default mute to Asia/Tokyo
(time zone of Japan), the result changes to April 4. This is because Date
represents a specific moment in the timeline (a timestamp), and this timestamp corresponds to a different date and time in each part of the world. And the SimpleDateFormat
need to use a specific Timezone to know what date and time values to use to generate the String
.
Not to depend on Timezone default and always get the same result, just set a specific Timezone on SimpleDateFormat
:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("America/Sao_Paulo"));
With that, the SimpleDateFormat
will always use Timezone America/Sao_Paulo
, independent of Timezone default that is set in the JVM.
Locales
Another feature of SimpleDateFormat
is to be able to format the date using different languages. To do this, just use a java.util.Locale
. For example, to have the month name in Portuguese:
SimpleDateFormat sdf = new SimpleDateFormat("dd 'de' MMMM 'de' yyyy", new Locale("pt", "BR"));
System.out.println(sdf.format(date)); // 03 de Abril de 2019
If you do not specify a Locale
, will be used the default JVM. If you already know the language to be used, pass the Locale
corresponding in the manufacturer.
Both Timezone and locale default can be changed at runtime by any application running on the same JVM. So, if you already know you need a specific Timezone or locale, use them explicitly as indicated above.
Parsing
The Parsing also requires some care. For example, this code:
TimeZone.setDefault(TimeZone.getTimeZone("America/Sao_Paulo"));
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = sdf.parse("03/04/2019");
System.out.println(date); // Wed Apr 03 00:00:00 BRT 2019
The entry only has day, month and year, but the result was Wed Apr 03 00:00:00 BRT 2019
. Notice that the time has been set for midnight, and BRT
refers to tiemzone default of my JVM (which in this case is America/Sao_Paulo
).
Like Date
represents a timestamp and only with the day, month and year it is not possible to obtain this value, SimpleDateFormat
completes missing information with values default. In case, midnight for the time and the Timezone default from the JVM to get the time zone. But if I set another Timezone, the result will be different:
TimeZone.setDefault(TimeZone.getTimeZone("America/Sao_Paulo"));
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));
Date date = sdf.parse("03/04/2019");
System.out.println(date); // Tue Apr 02 12:00:00 BRT 2019
Now the SimpleDateFormat
will use "midnight on Timezone Asia/Tokyo
". So the result is Tue Apr 02 12:00:00 BRT 2019
because when it’s midnight on the 3rd in Tokyo, it’s still noon on the 2nd in Brazil.
This is a caution that few take, because generally the servers are configured in the "correct" Timezone and everything "works". But it is enough to change the configuration (by mistake or purposely, it does not matter), or someone innocently call TimeZone.setDefault
and the system starts to enter wrong dates. If you know that the dates will be in a specific Timezone, pass it to setTimeZone
.
There are still other details to consider when using this class, here are some links listing these problems: