Java SimpleDateFormat Wrong Timezone after parsing - java

Why: When I give input date string with GMT timezone, SimpleDateFormat parses it and outputs EET timezone?
public static String DATE_FORMAT="dd MMM yyyy hh:mm:ss z";
public static String CURRENT_DATE_STRING ="31 October 2011 11:19:56 GMT";
...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(simpleDateFormat.parseObject(CURRENT_DATE_STRING));
And the output is:
Mon Oct 31 13:19:56 EET 2011
rather than
Mon Oct 31 13:19:56 GMT 2011

You're printing out the result of Date.toString(). A Date doesn't have any concept of a timezone - it's just the number of milliseconds since the UTC Unix epoch. Date.toString() always uses the system default time zone.
Note that you shouldn't be expecting "Mon Oct 31 13:19:56 GMT 2011" given that you've given a time which specifies a GMT hour of 11, not 13.
If you want to use a specific time zone for printing, you should use another DateFormat for the printing, rather than using Date.toString(). (Date.toString() keeps causing confusion like this; it's really unfortunate.)

java.util.Date does not hold timezone information.
A java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone.
Apart from this, there are a couple of problems with your code:
Use H instead of h for the 24-Hour format. The letter, h is used for the 12-Hour format (i.e. with AM/PM marker).
Even though MMM works for parsing the long name of the month (e.g. January) with SimpleDateFormat, it is meant for the 3-letter month name (e.g. Jan). If you try doing it with the modern Date-Time API, you will be greeted with the DateTimeParseException. You should use MMMM for the long name of the month.
Demo incorporating these points:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String strDateTime = "31 October 2011 11:19:56 GMT";
SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy HH:mm:ss z", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = sdf.parse(strDateTime);
String strDate = sdf.format(date);
System.out.println(strDate);
// Some other format
sdf = new SimpleDateFormat("MMMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
strDate = sdf.format(date);
System.out.println(strDate);
// The last format with some other timezone
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
strDate = sdf.format(date);
System.out.println(strDate);
}
}
Output:
31 October 2011 11:19:56 GMT
October 31 11:19:56 GMT 2011
October 31 07:19:56 EDT 2011
ONLINE DEMO
Switch to java.time API.
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "31 October 2011 11:19:56 GMT";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd MMMM uuuu HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
// Some other format
DateTimeFormatter dtfAnother = DateTimeFormatter.ofPattern("MMMM dd HH:mm:ss z uuuu", Locale.ENGLISH);
String strDate = dtfAnother.format(zdt);
System.out.println(strDate);
}
}
Output:
2011-10-31T11:19:56Z[GMT]
October 31 11:19:56 GMT 2011
ONLINE DEMO
The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Related

Joda Time toDate() wrong result

I am using this code:
date - Date object from DatePicker, as string Thu Sep 10 00:00:00 GMT+03:00 2020
mDate = DateTime(date)
.withHourOfDay(0)
.withMinuteOfHour(0)
.withSecondOfMinute(0)
.withMillisOfSecond(0)
.toDate()
The result
mDate - Wed Sep 09 03:00:00 GMT+03:00 2020
What wrong with this?
You are not converting the DateTime object to java.util.Date correctly. A correct way is to get the milliseconds from DateTime object and initialize the java.util.Date with the milliseconds.
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Define formatter
DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zZ yyyy");
// Date-time string from DatePicker
String strDateTime = "Thu Sep 10 00:00:00 GMT+03:00 2020";
DateTime dateTime = DateTime.parse(strDateTime, formatter);
System.out.println(dateTime);
// No. of milliseconds from the epoch of 1970-01-01T00:00:00Z
long millis = dateTime.getMillis();
System.out.println(millis);
Date mDate = new Date(millis);
// Display java.util.Date object in my default time-zone (BST)
System.out.println(mDate);
//Display java.util.Date in a different time-zone and using custom format
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+3"));
System.out.println(sdf.format(mDate));
}
}
Output:
2020-09-09T21:00:00.000Z
1599685200000
Wed Sep 09 22:00:00 BST 2020
Thu Sep 10 00:00:00 GMT+03:00 2020
Note: java.util.Date does not represent a Date/Time object. It simply represents the no. of milliseconds from the epoch of 1970-01-01T00:00:00Z. It does not have any time-zone or zone-offset information. When you print it, Java prints the string obtained by applying the time-zone of your JVM. If you want to print it in some other timezone, you can do so using the SimpleDateFormat as shown above.
I recommend you switch from the outdated and error-prone java.util date-time API and SimpleDateFormat to the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time. If your Android API level is still not compliant with Java8, check How to use ThreeTenABP in Android Project and Java 8+ APIs available through desugaring.
The following table shows an overview of modern date-time classes:

Unparseable date with symbolic timezone [duplicate]

I'm always getting the parse exception even if the format to check and the string value are same.
Here is the code:
String format = "EEE MMM dd HH:mm:ss z yyyy";
String value = "Mon Sep 18 10:30:06 MST 2017";
public static boolean isValidFormat(String format, String value) {
Date date = null;
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
date = sdf.parse(value); // here it breaks
if (!value.equals(sdf.format(date))) {
date = null;
}
} catch (ParseException ex) {
ex.printStackTrace(); //java.text.ParseException: Unparseable date:
"Mon Sep 18 10:30:06 MST 2017" (at offset 0)
}
return date != null;
}
It says that your date-time string is unparseable at index 0. Index 0 is where it says Mon, so the three letter time zone abbreviation is not the first suspect. The locale is. “Mon” works as abbreviation for Monday in English, but not in very many other languages. So if your device has a non-English language setting — maybe it has even been changed recently — this will fully explain your observation.
The shortsighted solution is
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.ROOT);
I use Locale.ROOT to mean that no language specific processing should be done. If your string is in English because English is generally the language used in computing around the globe, I would consider this choice appropriate. If on the other hand it is in English because it comes from an English speaking locale, that locale will be the right one to use.
With this change, on my computer your code formats your date into Mon Sep 18 11:30:06 MDT 2017, which, as you can see is not the same as the value we started out from, so your method returns false. My JVM understood MST as Mountain Standard Time, and then assumed summer time (DST) in September and formatted the string accordingly.
ThreeTenABP
That said, Date and SimpleDateFormat are long outdated classes. You should give it a thought to get rid of them and use the modern Java date and time API instead. On Android you get it in the ThreeTenABP, see this question: How to use ThreeTenABP in Android Project. Now you may do:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format, Locale.ROOT);
try {
return ZonedDateTime.parse(value, dtf).format(dtf).equals(value);
} catch (DateTimeParseException dtpe) {
dtpe.printStackTrace();
return false;
}
This behaves the same as above.
Three letter time zone abbreviations
You should avoid the three and four letter time zone abbreviations where you can. They are not standardized and generally ambiguous. MST, for example, may mean Malaysia Standard Time or Mountain Standard Time. The latter isn’t even a full time zone, since MDT is used for the greater part of the year, which caused the trouble I observed as I said above.
Instead, see if you can get a string in ISO 8601 format, like 2017-09-18T10:30:06+08:00. Second best, just get something unambiguous. One way is to include an offset from UTC rather than a time zone ID (or both).
Never use SimpleDateFormat or DateTimeFormatter without a Locale
Since the given date-time is in English, you should use Locale.ENGLISH with your date-time parser; otherwise the parsing will fail in a system (computer, phone etc.) which is using a non-English type of locale.
Also, note that the date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Demo:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final String strDateTime = "Mon Sep 18 10:30:06 MST 2017";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
2017-09-18T10:30:06-06:00[America/Denver]
An important note about timezone before we proceed further:
Avoid specifying a timezone with the 3-letter abbreviation. A timezone should be specified with a name in the format, Region/City e.g. ZoneId.of("Europe/London"). With this convention, the ZoneId for UTC can be specified with ZoneId.of("Etc/UTC"). A timezone specified in terms of UTC[+/-]Offset can be specified as Etc/GMT[+/-]Offset e.g. ZoneId.of("Etc/GMT+1"), ZoneId.of("Etc/GMT+1") etc.
There are some exceptional cases as well e.g. to specify the timezone of Turkey, we use
ZoneId.of("Turkey")
The following code will give you all the available ZoneIds:
// Get the set of all time zone IDs.
Set<String> allZones = ZoneId.getAvailableZoneIds();
You should ask your server application to provide you with the date-time using this convention e.g.
Mon Sep 18 10:30:06 America/Denver 2017
The above code, without any change, will work for this date-time string.
Coming back to the original topic:
By default, DateTimeFormatter#ofPattern uses the default FORMAT locale which the JVM sets during startup based on the host environment. Same is the case with SimpleDateFormat. I have tried to illustrate the problem through the following demo:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final String strDateTime = "Mon Sep 18 10:30:06 America/Denver 2017";
DateTimeFormatter dtfWithDefaultLocale = null;
System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + ZonedDateTime.parse(strDateTime, dtfWithDefaultLocale));
// Setting the JVM's default locale to Locale.FRANCE
Locale.setDefault(Locale.FRANCE);
// Using DateTimeFormatter with Locale.ENGLISH explicitly (recommended)
DateTimeFormatter dtfWithEnglishLocale = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu", Locale.ENGLISH);
System.out.println("JVM's Locale: " + Locale.getDefault());
System.out.println("DateTimeFormatter's Locale: " + dtfWithEnglishLocale.getLocale());
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtfWithEnglishLocale);
System.out.println("Parsed with Locale.ENGLISH: " + zdt);
System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + ZonedDateTime.parse(strDateTime, dtfWithDefaultLocale));
}
}
Output:
JVM's Locale: en_GB
DateTimeFormatter's Locale: en_GB
Parsed with JVM's default locale: 2017-09-18T10:30:06-06:00[America/Denver]
JVM's Locale: fr_FR
DateTimeFormatter's Locale: en
Parsed with Locale.ENGLISH: 2017-09-18T10:30:06-06:00[America/Denver]
JVM's Locale: fr_FR
DateTimeFormatter's Locale: fr_FR
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon Sep 18 10:30:06 America/Denver 2017' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:598)
at Main.main(Main.java:32)
The following demo, using SimpleDateFormat, is just for the sake of completeness:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
final String strDateTime = "Mon Sep 18 10:30:06 MST 2017";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM d H:m:s z yyyy", Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
System.out.println(date);
}
}
Output:
Mon Sep 18 18:30:06 BST 2017
Note: The java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the milliseconds from the Epoch of January 1, 1970. When you print an object of java.util.Date, its toString method returns the date-time calculated from this milliseconds value. Since java.util.Date does not have timezone information, it applies the timezone of your JVM and displays the same. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFomrat and obtain the formatted string from it.
Here is the code of dateformatter which will hep you to convert your date into any time format.
public void setDate(String date) {
dateInput = (TextView) itemView.findViewById(R.id.dateText);
DateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
try {
dateData = inputFormat.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
DateFormat outputFormat = new SimpleDateFormat("pur your desirable format");
String outputString = outputFormat.format(dateData);
dateInput.setText(outputString);
}
I use the almost use the same code as you do with only slight difference in SimpleDateFormat instantiation.
public static final String DATE_FORMAT = "EEE MMM d yyyy z HH:mm:ss";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.ROOT);
simpleDateFormat.format(date);
It returns Mon Sep 18 2017 GMT+03:00 23:04:10.

how to parse the following date format Mon Nov 09 2015 00:00:00 GMT+0530 (India Standard Time) in java

I am getting the date in the format Mon Nov 09 2015 00:00:00 GMT+0530 (India Standard Time). I have to convert it to sql date of format dd/MM/yyyy. Please help.
I tried below code but did not help
Date date = new java.sql.Date(
(new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zz (zzzz)").parse("Mon Nov 09 2015 00:00:00 GMT+0530 (India Standard Time)"))
.getTime());
Something like below, also refer here for Java SimpleDateFormat
public static void main(String[] args) throws ParseException {
String time = "Mon Nov 09 2015 00:00:00 GMT+0530 (India Standard Time)";
DateFormat inputFormat = new SimpleDateFormat(
"E MMM dd yyyy HH:mm:ss 'GMT'z", Locale.ENGLISH);
Date date = inputFormat.parse(time);
System.out.println(date);
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy", Locale.US);
System.out.println(formatter.format(date));
}
output
Mon Nov 09 00:00:00 IST 2015
09/11/2015
The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API* .
Since your date-time string has timezone information, parse it into ZonedDateTime which you can convert to other java.time types and if required, format into the desired formats.
Demo:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon Nov 09 2015 00:00:00 GMT+0530 (India Standard Time)";
DateTimeFormatter dtfInput = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("E MMM d uuuu H:m:s")
.appendLiteral(" ")
.appendZoneId()
.appendPattern("X")
.appendLiteral(" ")
.appendLiteral("(")
.appendGenericZoneText(TextStyle.FULL)
.appendLiteral(')')
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtfInput);
OffsetDateTime odt = zdt.toOffsetDateTime();
System.out.println(odt);
// To LocalDate, LocalDateTime etc.
LocalDate localDate = odt.toLocalDate();
LocalDateTime localDateTime = odt.toLocalDateTime();
System.out.println(localDate);
System.out.println(localDateTime);
// Get the formatted string
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ENGLISH);
String formatted = dtfOutput.format(localDate);
System.out.println(formatted);
// In UTC
odt = odt.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odt);
}
}
Output:
2015-11-09T00:00+05:30
2015-11-09
2015-11-09T00:00
09/11/2015
2015-11-08T18:30Z
Learn more about the modern date-time API from Trail: Date Time.
Support for OffsetDateTime in JDBC:
Starting with JDBC 4.2, you can use OffsetDateTime directly in your code e.g.
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();
The support for java.time API in JDBC Java SE 8 (JDBC 4.2) came without requiring any public JDBC API changes. The setObject and getObject methods support java.time types as per the following mapping:
Note for PostgreSQL™: ZonedDateTime, Instant and OffsetTime / TIME WITH TIME ZONE are not supported. Also, the OffsetDateTime instances need to be in UTC (have offset 0).
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
I have dealt with something like this right now, and this is my solution:
String dateString = new SimpleDateFormat("dd/MM/yyyy").format(timestamp.toDate()).toString();

Input date Jan 03 but returns Jan 02, why?

public static void main(String[] args) {
String opDate = "Tue Jan 03 00:00:00 MSK 2006";
String date = convertDate(opDate, "yyyyMMdd");
System.out.println("opDate: " + opDate);
System.out.println("date: " + date);
}
public static String convertDate(String opDate, String dateFormat) {
Date date = new Date();
// Mon Jan 02 00:00:00 MSK 2006
SimpleDateFormat dateParser = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
try {
date = dateParser.parse(opDate);
} catch (Exception e) {
System.out.println("exception = " + e.toString());
}
SimpleDateFormat df = new SimpleDateFormat(dateFormat);
df.setTimeZone(TimeZone.getTimeZone("Russia/Moscow"));
String strDate = df.format( date.getTime() );
return strDate.trim();
}
out:
opDate: Tue Jan 03 00:00:00 MSK 2006
date: 20060102
Why does it return Jan 02?
The problem is the fetching of the "Russia/Moscow" time zone. The correct zoneinfo ID is "Europe/Moscow". Change the ID, and the problem goes away:
df.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
It's unfortunate that TimeZone.getTimeZone("random rubbish") returns the UTC time zone rather than letting you know in some way that it's broken.
Probably due to timezone conversion.
I would suggest you also print the time and the timezone of your resulting date. This is likely to be Jan 2, 23:00 or something.
This happens because you set a different timezone on the SimpleDataFormat.
Timezones.
You're specifying midnight on January 3rd in MSK. This is 9pm on the 2nd January in GMT (the likely default timezone).
I can see that you're trying to output in Moscow time as well, but Russia/Moscow is not a valid timezone, and the getTimeZone call "helpfully" silently defaults to returning GMT. This then of course doesn't change the time zone of the date when formatting and outputs it as 2 Jan.
If you set the timezone to Europe/Moscow, you'll get the expected output.
May it be related to the fact that you're converting dates between two distinct TimeZones?
If you change line:
String date = convertDate(opDate, "yyyyMMdd");
to:
String date = convertDate(opDate, "EEE MMM dd HH:mm:ss zzz yyyy");
you can see the output of your program:
opDate: Tue Jan 03 00:00:00 MSK 2006
date: Mon Jan 02 20:00:00 GMT 2006
You are not setting well TimeZone with:
df.setTimeZone(TimeZone.getTimeZone("Russia/Moscow"));
you need:
df.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
Finally there are summer delay of 1h.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Tue Jan 03 00:00:00 MSK 2006";
String formatted = formatDateTimeStringTo(strDateTime, "yyyyMMdd", Locale.ENGLISH);
System.out.println("opDate: " + strDateTime);
System.out.println("date: " + formatted);
}
public static String formatDateTimeStringTo(String strDateTime, String targetFormat, Locale locale) {
DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE MMM d H:m:s zzz u", locale);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(targetFormat, locale);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, parser);
// System.out.println(zdt); // 2006-01-03T00:00+03:00[Europe/Moscow]
return zdt.format(formatter);
}
}
Output:
opDate: Tue Jan 03 00:00:00 MSK 2006
date: 20060103
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Follow the standard convention to name the timezone:
Ask your publisher to switch to the standard naming convention of the timezone. The standard naming convention is Region/City e.g. Europe/Moscow. The two/three/four letter abbreviation for the timezone is error-prone as described in the following text at the Timezone documentation page:
Three-letter time zone IDs
For compatibility with JDK 1.1.x, some other three-letter time zone
IDs (such as "PST", "CTT", "AST") are also supported. However, their
use is deprecated because the same abbreviation is often used for
multiple time zones (for example, "CST" could be U.S. "Central
Standard Time" and "China Standard Time"), and the Java platform can
then only recognize one of them.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

How to parse a date? [duplicate]

This question already has answers here:
Java string to date conversion
(17 answers)
Closed 6 years ago.
I am trying to parse this date with SimpleDateFormat and it is not working:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Formaterclass {
public static void main(String[] args) throws ParseException{
String strDate = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date dateStr = formatter.parse(strDate);
String formattedDate = formatter.format(dateStr);
System.out.println("yyyy-MM-dd date is ==>"+formattedDate);
Date date1 = formatter.parse(formattedDate);
formatter = new SimpleDateFormat("dd-MMM-yyyy");
formattedDate = formatter.format(date1);
System.out.println("dd-MMM-yyyy date is ==>"+formattedDate);
}
}
If I try this code with strDate="2008-10-14", I have a positive answer. What's the problem? How can I parse this format?
PS. I got this date from a jDatePicker and there is no instruction on how modify the date format I get when the user chooses a date.
You cannot expect to parse a date with a SimpleDateFormat that is set up with a different format.
To parse your "Thu Jun 18 20:56:02 EDT 2009" date string you need a SimpleDateFormat like this (roughly):
SimpleDateFormat parser=new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Use this to parse the string into a Date, and then your other SimpleDateFormat to turn that Date into the format you want.
String input = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Date date = parser.parse(input);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = formatter.format(date);
...
JavaDoc: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
The problem is that you have a date formatted like this:
Thu Jun 18 20:56:02 EDT 2009
But are using a SimpleDateFormat that is:
yyyy-MM-dd
The two formats don't agree. You need to construct a SimpleDateFormat that matches the layout of the string you're trying to parse into a Date. Lining things up to make it easy to see, you want a SimpleDateFormat like this:
EEE MMM dd HH:mm:ss zzz yyyy
Thu Jun 18 20:56:02 EDT 2009
Check the JavaDoc page I linked to and see how the characters are used.
We now have a more modern way to do this work.
java.time
The java.time framework is bundled with Java 8 and later. See Tutorial. These new classes are inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. They are a vast improvement over the troublesome old classes, java.util.Date/.Calendar et al.
Note that the 3-4 letter codes like EDT are neither standardized nor unique. Avoid them whenever possible. Learn to use ISO 8601 standard formats instead. The java.time framework may take a stab at translating, but many of the commonly used codes have duplicate values.
By the way, note how java.time by default generates strings using the ISO 8601 formats but extended by appending the name of the time zone in brackets.
String input = "Thu Jun 18 20:56:02 EDT 2009";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM d HH:mm:ss zzz yyyy" , Locale.ENGLISH );
ZonedDateTime zdt = formatter.parse ( input , ZonedDateTime :: from );
Dump to console.
System.out.println ( "zdt : " + zdt );
When run.
zdt : 2009-06-18T20:56:02-04:00[America/New_York]
Adjust Time Zone
For fun let's adjust to the India time zone.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );
zdtKolkata : 2009-06-19T06:26:02+05:30[Asia/Kolkata]
Convert to j.u.Date
If you really need a java.util.Date object for use with classes not yet updated to the java.time types, convert. Note that you are losing the assigned time zone, but have the same moment automatically adjusted to UTC.
java.util.Date date = java.util.Date.from( zdt.toInstant() );
How about getSelectedDate? Anyway, specifically on your code question, the problem is with this line:
new SimpleDateFormat("yyyy-MM-dd");
The string that goes in the constructor has to match the format of the date. The documentation for how to do that is here. Looks like you need something close to "EEE MMM d HH:mm:ss zzz yyyy"
In response to:
"How to convert Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México)) to dd-MM-yy in Java?", it was marked how duplicate
Try this:
With java.util.Date, java.text.SimpleDateFormat, it's a simple solution.
public static void main(String[] args) throws ParseException {
String fecha = "Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México))";
Date f = new Date(fecha);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("-5GMT"));
fecha = sdf.format(f);
System.out.println(fecha);
}

Categories