Just to update the answers (which are not wrong), from Java 8 you can use the API java.time
to manipulate dates.
This API works in a similar way, but there is some important differences in relation to Date
and SimpleDateFormat
. The main one is that there are fewer implicit behaviors (many common with SimpleDateFormat
) and so the first impression is that it is more "complicated" by requiring a greater understanding of how the dates work.
For example, the abbreviation of Timezone ("BRT", which corresponds to "Brasília Time" - the famous Time of Brasilia) is an ambiguous information. Therefore the abbreviations are not considered timezones in fact, precisely because they are not standardized and there is a lot of ambiguity. Examples include "IST", which is used in India, Ireland and Israel, or "CST", which is used in China, Cuba and the United States.
Because they have many ambiguous abbreviations, it is not always possible to obtain a single corresponding Timezone. The only way to not have an ambiguous Timezone is to use the nomenclature of IANA. The abbreviation BRT, for example, corresponds to Timezone America/Sao_Paulo
(the IANA uses the name of the continent and the region’s most populous city to name the timezones), but also corresponds to America/Recife
, which during part of the year is equal to America/Sao_Paulo
, but it’s different during summer time - in fact, during summer time the abbreviation changes to BRST (Brasilia Summer Time), but only in states that follow the same rules of America/Sao_Paulo
. Those who follow America/Recife
continues to be BRT, as these do not have summer time (according to current rules).
As they present these differences during the year, IANA considers that America/Sao_Paulo
and America/Recife
are two different timezones. The fact that they have the same time - and the same abbreviation - for part of the year is just a detail.
Anyway, I just said all this because SimpleDateFormat
simply assume some Timezone when an abbreviation is passed (and in cases of ambiguity there is no way to control which will be used). Already in the new API we have to specify which Timezone we want to use.
Another difference is that there are several different types to represent dates: one only with the day, month and year, another only with the time, another with date, time and Timezone, etc. So one should choose the appropriate type according to the data you are working on.
In this case, the input string has date, time and Timezone, so the type indicated is java.time.ZonedDateTime
. To transform the string into a date, use a java.time.format.DateTimeFormatter
. And to configure the Timezone to be used (because the abbreviation is ambiguous and we should set a Timezone), we use a java.time.format.DateTimeFormatterBuilder
.
To set the Timezone, use a java.time.ZoneId
with the name of Timezone in the format of IANA. It is possible to pass several timezones, so these are placed in a java.util.Set
:
// timezone a ser usado para a abreviação
Set<ZoneId> zones = new HashSet<>();
zones.add(ZoneId.of("America/Sao_Paulo"));
// criar o DateTimeFormatter
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// data e hora
.appendPattern("EEE MMM dd HH:mm:ss ")
// abreviação do timezone (usar java.time.format.TextStyle)
.appendZoneText(TextStyle.SHORT, zones)
// ano
.appendPattern(" uuuu")
// usar locale inglês para o dia da semana e mês
.toFormatter(Locale.ENGLISH);
// transformar a string em data
ZonedDateTime datetime = ZonedDateTime.parse("Sun Oct 05 20:59:57 BRT 2014", fmt);
Notice I used the java.util.Locale
corresponding to the English language, because the day of the week and the month are in English. If you do not specify a locale, the configuration will be used default JVM, and may not always be the language you need. It is best to set locale if you already know which language is used.
To better understand what letters are EEE MMM ...
, see the documentation. A lot of attention because not everything is equal to SimpleDateFormat
. Some letters work the same way, others in a similar way, others in a completely different way, etc.
To save in bank, you can convert to a java.sql.Timestamp
, for example. In Java 8 conversion methods have been added for ease. The method from
gets a java.time.Instant
, which may be obtained from ZonedDateTime
using the method toInstant()
:
// converter para java.sql.Timestamp
Timestamp ts = Timestamp.from(datetime.toInstant());
And to convert back to ZonedDateTime
, we use the method toInstant()
, that returns a Instant
, and then the method atZone
, that converts the Instant
for the Timezone indicated:
// converter Timestamp para ZonedDateTime
ZonedDateTime zdt = ts.toInstant().atZone(ZoneId.of("America/Sao_Paulo"));
And you can get the original string using the same DateTimeFormatter
to format the date:
String dateStr = zdt.format(fmt);
If the bank you are using has a driver compatible with the JDBC 4.2, it is possible to work directly with the Instant
, using the methods setObject
class java.sql.PreparedStatement
and getObject
class java.sql.ResultSet
:
PreparedStatement ps = ...
// seta o java.time.Instant
ps.setObject(1, datetime.toInstant());
// obter o Instant do banco
ResultSet rs = ...
Instant instant = rs.getObject(1, Instant.class);
// converter o instant para o timezone
ZonedDateTime zdt = instant.atZone(ZoneId.of("America/Sao_Paulo"));
You’ve tried something before and made a mistake?
– Mega