This question already has answers here:
Parsing SimpleDateFormat
(2 answers)
Closed 6 years ago.
public static void main(String[] args) {
Date now = new Date();
String dateString = now.toString();
System.out.println(" 1. " + dateString);
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
try {
Date parsed = format.parse(dateString);
System.out.println(" 2. " + parsed.toString());
} catch (ParseException pe) {
System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
}
System.out.println(" 3. " + format.format(now));
}
print in console:
1. Thu Feb 23 17:14:51 CET 2017
ERROR: Cannot parse "Thu Feb 23 17:14:51 CET 2017"
3. jeu. févr. 23 05:14:51 CET 2017
instead of:
1. Thu Feb 23 17:14:51 CET 2017
2. Thu Feb 23 17:14:51 CET 2017
3. jeu. févr. 23 05:14:51 CET 2017
It looks like your default Locale is FRENCH, and since SimpleDateFormat uses it if you don't specify another one, you can't successfully parse english abreviations like Thu or Feb.
However, you can specify the use of the ENGLISH Locale like this:
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
You have run into one of the many diseases of the now out-dated Date class in Java.
The sound and easy fix is to change over to the Java 8 date and time classes. The new class that best corresponds to Date is Instant. With this class your code becomes:
Instant now = Instant.now();
String dateString = now.toString();
System.out.println(" 1. " + dateString);
try {
Instant parsed = Instant.parse(dateString);
System.out.println(" 2. " + parsed.toString());
} catch (DateTimeParseException e) {
System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
}
I have left out 3. from your example. Of course it is possible to format the Instant in about any way you could dream of, but if we just want the same output as from the toString method I don’t find it worth it for now. Rather I would like to show that for this case you don’t need a format at all. The code prints:
1. 2017-02-23T17:07:19.775Z
2. 2017-02-23T17:07:19.775Z
You notice that it prints the time in UTC. If you want your local time zone instead, just use ZonedDateTime instead of Instant. The rest of the code is exactly the same, but now output on my computer is:
1. 2017-02-23T18:07:19.852+01:00[Europe/Berlin]
2. 2017-02-23T18:07:19.852+01:00[Europe/Berlin]
Of course it is possible to generate an error like the one you get from disagreeing locales also with the new classes. As far as I can see, you would have to explicitly specify disagreeing locales. So you don’t do it easily.
Related
I have an array of Strings with the dates e.g.:
Tue, 09 Feb 2016 14:07:00 GMT;
Tue, 09 Feb 2016 19:55:00 GMT.
Now I want to find the most recent date on this list. In order to do that, I try to deserialize these strings to java.util.Date objects and after that compare them.
The code sample of java.util.Date object generation:
strDate = "Tue, 09 Feb 2016 14:07:00 GMT";
DateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
Date date;
try {
date = format.parse(strDate);
//Result: Tue Feb 09 16:07:00 IST 2016
System.out.println("Result: " + date.toString());
} catch(ParseException e) {
e.printStackTrace();
}
My questions:
Why is the result in IST 2016 time zone and not in GMT? What does the IST 2016 stand for? Is it India Standard Time or Irish Standard Time or Israel Standard Time?
The initial string is in EEE, dd MMM format, the SimpleDateFormat pattern is also in this format, thus, why the result is in EEE, MMM dd format?
How can get a java.util.Date object in the same timezone as the initial string, in my case — GMT?
Is the approach I'm using to find the most recent date in the list is OK or there is more convenient/modern way to do that in Java 8, e.g., with the usage of LocalDateTime?
You are relying to Date.toString() to print your date when you should format it to a String with a formatter. What you are seeing is just the default pattern of Date.toString(). What you must keep in mind is that a Date does not have a timezone. You are seeing the output with the IST timezone, this must be because the current locale for the JVM is set to some specific locale for which the timezone name is "IST".
With regard to your point 4, yes, you can do it much cleaner with Java Time API introduced in Java 8. You can create a List of your strings to parse, create a DateTimeFormatter to parse it, and keep the maximum date value.
public static void main(String[] args) {
List<String> dates = Arrays.asList("Tue, 09 Feb 2016 14:07:00 GMT", "Tue, 09 Feb 2016 19:55:00 GMT");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime maxDate = dates.stream()
.map(s -> ZonedDateTime.parse(s, formatter))
.max(ZonedDateTime::compareTo)
.get(); // or .orElse(null)
System.out.println(maxDate);
}
This code is using a ZonedDateTime to keep the time-zone of the incoming strings.
Your computer seems to be set to IST. To force GMT output, import java.util.TimeZone and do this in your try block:
format.setTimeZone(TimeZone.getTimeZone("GMT"));
date = format.parse(strDate);
System.out.println("Result: " + format.format(date));
SimpleDateFormat formatter = new SimpleDateFormat(“EEE MMM dd HH:mm:ss zzz yyyy”);
Date date= null ;
date = formatter.parse(String.valueOf(m.getSentDate()));
formatter = new SimpleDateFormat(“dd.MM.yyyy”);
tarih=formatter.format(date);
ERROR = “java.text.ParseException: Unparseable date: “Wed Jan 20 15:13:09 EET 2016″ (at offset 0)”
I get this error code permanently
java mail api from history= Mon jan 18 21:17:31 ETT 2016
I want to convert methods = 18.01.2016 21:17:31
I'm sorry my bad english
Your formatter should be working. So something else is wrong.
Here is my example code using your formatter and your input string.
String input = "Wed Jan 20 15:13:09 EET 2016";
SimpleDateFormat formatter = new SimpleDateFormat ( "EEE MMM dd HH:mm:ss zzz yyyy" );
Date date = null;
try {
date = formatter.parse ( input );
} catch ( ParseException e ) {
System.out.println ( "Exception… " + e );
}
System.out.println ( "date: " + date + " | date via formatter: " + formatter.format ( date ) + " | as Instant: " + date.toInstant () );
When run.
date: Wed Jan 20 05:13:09 PST 2016 | date via formatter: Wed Jan 20 15:13:09 EET 2016 | as Instant: 2016-01-20T13:13:09Z
Curly-Quotes
I am seeing many curly-quotes in your code and output. Hopefully those are not in the original. Curly quotes are typographically nice but inappropriate in programming code.
If you are using word-processors for your programming, stop that. They are not built for programming and will inject these curly-quotes among many other problems. Learn to use text editors intended for programming source code.
java.time
By the way, the old java.util.Date/.Calendar classes are notoriously troublesome. They have been supplanted in Java 8 and later by the new built-in java.time framework.
I am converting from epoch time (which is in UTC) to a format as shown below. Now I tried different SO answers to convert UTCDate from UTC to local time. But I am not getting the local time.
Any help would be appreciated.
String epochTime = "1436831775043";
Date UTCDate = new Date(Long.parseLong(epochTime));
Date localDate; // How to get this?
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("h:mm a");
String result = simpleDateFormat.format(UTCDate);
Also, the conversion has to be done without the help of any external library.
Java 8
String epochTime = "1436831775043";
Instant utcInstant = new Date(Long.parseLong(epochTime)).toInstant();
ZonedDateTime there = ZonedDateTime.ofInstant(utcInstant, ZoneId.of("UTC"));
System.out.println(utcInstant);
LocalDateTime here = there.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(here);
Which outputs:
2015-07-13T23:56:15.043Z
2015-07-14T09:56:15.043
After thoughts...
I think you're chasing your tail. Date is just a container for the number of milliseconds since the epoch (January 1, 1970, 00:00:00 GMT). It doesn't internally carry a representation of a time zone (AFAIK).
For example...
String epochTime = "1436831775043";
Date UTCDate = new Date(Long.parseLong(epochTime));
// Prints the "representation" of the Date
System.out.println(UTCDate);
// Local date/time format...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy h:mm:ss a");
try {
System.out.println("local format: " + simpleDateFormat.format(UTCDate));
System.out.println("local Date: " + simpleDateFormat.parse(simpleDateFormat.format(UTCDate)));
} catch (ParseException ex) {
Logger.getLogger(JavaApplication203.class.getName()).log(Level.SEVERE, null, ex);
}
// UTC date/time format
try {
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("utc format: " + simpleDateFormat.format(UTCDate));
System.out.println("utc date: " + simpleDateFormat.parse(simpleDateFormat.format(UTCDate)));
} catch (ParseException ex) {
Logger.getLogger(JavaApplication203.class.getName()).log(Level.SEVERE, null, ex);
}
Which outputs...
Tue Jul 14 09:56:15 EST 2015
local format: 14/07/2015 9:56:15 AM
local Date: Tue Jul 14 09:56:15 EST 2015
utc format: 13/07/2015 11:56:15 PM
utc date: Tue Jul 14 09:56:15 EST 2015
If you have a look at local Date and utc date they are the same thing, even though the local format and utc format are formatted correctly.
So, instead of chasing your tale trying to get Date to "represent" a value you want, either use Java 8's Time API or JodaTime to manage the Time Zone information or simply format the Date into the Time Zone you want...
Further, if we do something like...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy h:mm:ss a");
Date localDate = simpleDateFormat.parse(simpleDateFormat.format(UTCDate));
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date utcDate = simpleDateFormat.parse(simpleDateFormat.format(UTCDate));
System.out.println(localDate.getTime());
System.out.println(utcDate.getTime());
System.out.println(localDate.equals(utcDate));
It will print...
1436831775000
1436831775000
true
You can set your time zone in the formatter:
simpleDateFormat.setTimeZone(TimeZone.getDefault());
Calendar cal= Calendar.getInstance();
System.out.println(cal.getTimeZone().getID());
cal.set(2012, 8, 21);
java.util.Date d = new java.util.Date();
System.out.println(d.toString());
//System.setProperty("user.timezone", "America/Chicago");
// System.out.println(TimeZone.getDefault().getID());
TimeZone tz1 = TimeZone.getTimeZone("Africa/Algiers");
//tz1.setDefault(tz1);
cal.setTimeZone(tz1);
System.out.println(cal.getTimeZone().getID());
//cal.set(2012, 8, 21);
System.out.println(d.toString());
Output is --
Asia/Calcutta
Tue Aug 21 11:35:06 IST 2012
Africa/Algiers
Tue Aug 21 11:35:06 IST 2012
I want the time in the currrent timezone format but it is giving in IST. How to do this.
EDIT: I've only just noticed that the code you're given doesn't even call cal.getTime(). You're completely ignoring the value in the calendar. It wouldn't do what you wanted anyway, but the value you're printing is just new Date()... how do you expect the calendar to get involved?
I want the time in the currrent timezone format but it is giving in IST. How to do this.
Avoid using Date.toString, to start with. A Date value has no concept of a time zone, so toStringjust uses the system time zone, always. Changing the time zone of a calendar without calling set again doesn't change the underlying value, either.
Now there are two options:
Use SimpleDateFormat, specifying the time zone there before formatting
Use Joda Time instead, which is a much richer date and time API in the first place
Personally I'd strongly advise you to use the latter option, particularly if you're doing quite a bit of date/time manipulation. Date, Calendar and SimpleDateFormat just don't let you write code which clearly expresses what data you have at any point in time.
Use TimeZone.setDefault(tz1); instead of //tz1.setDefault(tz1);
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTimeZone().getID());
cal.set(2012, 8, 21);
java.util.Date d = new java.util.Date();
System.out.println(d.toString());
TimeZone tz1 = TimeZone.getTimeZone("Africa/Algiers");
TimeZone.setDefault(tz1);
cal.setTimeZone(tz1);
System.out.println(cal.getTimeZone().getID());
System.out.println(d.toString());
I run your program, see output :
Asia/Calcutta
Tue Aug 21 11:47:13 IST 2012
Africa/Algiers
Tue Aug 21 07:17:13 CET 2012
Calender doesnot work that way...i have SimpleDateFormat code..it may help..try this
public class TimeZoneTest {
public static void main(String[] args) {
new TimeZoneTest().setTimeZones();
}
private void setTimeZones(){
String etStart = "";
String ctStart = "";
String mtStart = "";
String ptStart = "";
DateFormat fullDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
String dateString = "Mon Mar 14 09:30:51 GMT 2011";
//this input date doesn't convert
//String dateString = "Mon Mar 14 09:30:51 PDT 2011";
System.out.println("Input Date: " + dateString);
System.out.println("Default TimeZone: " + TimeZone.getDefault());
try {
etStart = getDateInTimeZone(dateString, fullDateFormat, TimeZone.getTimeZone("America/New_York"));
ctStart = getDateInTimeZone(dateString, fullDateFormat, TimeZone.getTimeZone("America/Chicago"));
mtStart = getDateInTimeZone(dateString, fullDateFormat, TimeZone.getTimeZone("America/Denver"));
ptStart = getDateInTimeZone(dateString, fullDateFormat, TimeZone.getTimeZone("America/Los_Angeles"));
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Eastern Date: " + etStart);
System.out.println("Central Date: " + ctStart);
System.out.println("Mountain Date: " + mtStart);
System.out.println("Pacific Date: " + ptStart);
}
private String getDateInTimeZone(Date inputDt, TimeZone targetTimeZone) throws ParseException{
DateFormat fullDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
fullDateFormat.setTimeZone(targetTimeZone);
return fullDateFormat.format(inputDt);
}
}
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.