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: