From DateTimeFormatter javadoc:
Zone names: Time zone names ('z') cannot be parsed.
Therefore timezone parsing like:
System.out.println(new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").parse("Fri Nov 11 12:13:14 JST 2010"));
cannot be done in Joda:
DateTimeFormatter dtf = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss z yyyy");
System.out.println(dtf.parseDateTime("Fri Nov 11 12:13:14 JST 2010"));
//Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "Fri Nov 11 12:13:14 JST 2010" is malformed at "JST 2010"
//at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:673)
I think that the reason is that 'z' timezone names are conventional (not standardized) and ambiguous; i.e. they mean different things depending on your country of origin. For example, "PST" can be "Pacific Standard Time" or "Pakistan Standard Time".
If you are interested, this site has a listing of a large number of timezone names. It is not difficult to spot cases where there is ambiguity.
Probably because some time zone abbreviations are ambiguous and the parser can't know which time zone is meant.
It might of course also be one of the tiny, strange ticks and missing features you find after working with Joda for a while.
Abbreviated time zones are indeed ambiguous and Joda took a step further removing support for them as stated in the DateTimeZone javadoc:
Related
Is it possible to convert this date string using Java time package
3-6-2017
to this format
"Mon Mar 6 00:00:00 EST 2017"
I created these two formatters, but which time instance should I use? I've tried LocalDate, LocalDateTime, and ZonedDateTime.
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M-d-uuuu");
DateTimeFormatter convertedToFormat = DateTimeFormatter.ofPattern("EEE MMM dd hh:mm:ss zzz yyyy");
I believe that you have three issues:
To accept month in either 1 or 2 digits (like 3 for March and 11 for November) you need to specify one pattern letter M, not two. Similarly for day of month. So your input format pattern string should be M-d-uuuu (or just M-d-u). Edit: You also need d instead of dd in the “converted to” pattern.
To print hour of day (from 00 through 23) you need uppercase HH. Lowercase hh is for clock hour within AM or PM from 01 through 12.
Since your input string did not contain time of day, you need to specify time of day some other way. Similar for time zone since your “converted to” format contains zzz for time zone abbreviation.
So in code I suggest:
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("M-d-uuuu");
DateTimeFormatter convertedToFormat = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss zzz yyyy");
String input = "3-6-2017";
ZonedDateTime startOfDay = LocalDate.parse(input, inputFormat)
.atStartOfDay(ZoneId.of("America/New_York"));
String output = startOfDay.format(convertedToFormat);
System.out.println(output);
Output from my snippet is the desired:
Mon Mar 6 00:00:00 EST 2017
Or to answer your question a little more directly:
… which time instance should I use?
You need two of them: LocalDate for parsing your input and ZonedDateTime for formatting your output. And then a conversion between the two. The one-arg atStartOfDay method provides the conversion we need. (There is a trick for parsing directly into a ZonedDateTime using default values for time and time zone, but it’s more complicated.)
There are other time zones that will also produce EST as time zone abbreviation. Since your profile says you’re in Boston, I think that America/New_York is the one you want.
I need to parse a date string with timezone to Date object. The input date string pattern is:
"MM/dd/yyyy hh:mm a z" (eg: 04/30/2018 06:00 PM IST).
I have used below given code. But it returns incorrect date as output.
new SimpleDateFormat("MM/dd/yyyy hh:mm a z").parse("04/30/2018 06:00 PM IST")
Current Output: "Mon Apr 30 09:00:00 PDT 2018".
Expected Output: "Mon Apr 30 05:30:00 PDT 2018.
That's because timezone's abbreviations such as IST are ambiguous. IST is used in India, Israel and Ireland, and SimpleDateFormat assumes some of them as default, in obscure and undocumented ways (AFAIK). Actually, according to javadoc: "support of abbreviations is for JDK 1.1.x compatibility only and full names should be used".
One way to make it work is to arbitrarily choose a timezone and set it in the formatter:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm a z");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
Date date = sdf.parse("04/30/2018 06:00 PM IST");
Always use names in the format Continent/Region, such as Asia/Kolkata. Those names are IANA's timezones names, and they are not ambiguous, so this make things work.
java.time API
If you're using Java 8 or higher, switch to the java.time API, which is much better. For Java 7 or lower, there's the Threeten Backport with the same classes and functionality.
In this API, you must set a list of all preferred timezones to be used in case of ambiguous names like IST:
// prefered zones
Set<ZoneId> preferredZones = new HashSet<>();
preferredZones.add(ZoneId.of("Asia/Kolkata"));
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date and time
.appendPattern("MM/dd/yyyy hh:mm a ")
// zone (use set of prefered zones)
.appendZoneText(TextStyle.SHORT, preferredZones)
// use English, because different locales can affect timezones names
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse("04/30/2018 06:00 PM IST", fmt);
If you still need to use java.util.Date, it's easy to convert:
// Java 8
Date d = Date.from(zdt.toInstant());
// Java 7 (Threenten Backport)
Date d = DateTimeUtils.toDate(zdt.toInstant());
The resultant Date object will not hold any timezone information. See the similar query in this stackoverflow thread
You might be getting the correct date but in your JVM's current timezone.
In case if you are using Java 8, then there's a provision of Date object with timezone. Look at ZonedDateTime, but for this you need a different kind of formatter while parsing (DateTimeFormatter)
I have a timestamp 2018-01-01 18:20:23.11 which is in UTC. I need to print this in a different format but retain the UTC timezone. However if I use SimpleDateFormat ("dd MMM YYYY yyyy kk:mm z"), it takes my current timezone and gives me 01 Jan 2018 18:20 EST. I want this to print 01 Jan 2018 18:20 UTC. Doing a Timezone.getTimeZone("UTC") converts this time to UTC (does a +4 to hours)which is not the desired result.
DateTimeFormatter originalFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SS");
DateTimeFormatter newFormatter
= DateTimeFormatter.ofPattern("dd MMM uuuu HH:mm z", Locale.ENGLISH);
String originalTimestamp = "2018-01-01 18:20:23.11";
String differentFormat = LocalDateTime.parse(originalTimestamp, originalFormatter)
.atZone(ZoneId.of("Etc/UTC"))
.format(newFormatter);
System.out.println(differentFormat);
This prints
01 Jan 2018 18:20 UTC
ZoneId.of("Etc/UTC") or ZoneOffset.UTC?
A possibly nerdy edit: I had first written .atZone(ZoneOffset.UTC) in the conversion. I usually use ZoneOffset.UTC to denote UTC and consider this the nice and idiomatic way of specifying it. However in the case of your code, this resulted in the zone being given as Z in the output where you had asked for UTC. Using ZoneId.of("Etc/UTC") instead gives you what you want. I can find no other way of making sure that the zone is formatted as UTC (save hardcoding UTC in the format pattern string, but that would be an ugly hack).
BTW ZoneId.of("Etc/UTC").normalized() returns ZoneOffset.UTC (at least on my Java 10, but I expect it to be the case always).
SimpleDateFormat vs. java.time
SimpleDateFormat is not only long outdated, it is also notoriously troublesome. I recommend you avoid it. It is correct, as you have observed, that it uses your JVM’s default time zone. There is a way to persuade it to do differently, but I would not bother.
java.time is the modern Java date and time API. It came out in 2014 as a replacement for the old and poorly designed date and time classes. IMHO it is so much nicer to work with.
Link: Oracle tutorial: Date Time explaining how to use java.time
I read many of similar SO questions regarding this very topic, but I still am confused how to do it now... I try to make it simpel:
I got this String: "Sat Jan 24 00:00:00 GMT+100 2015"
which shall not be modified in any way
My question now is: What kind of pattern shall I use to parse this String into a java.util.Date? I tried: "EEE MMM dd HH:mm:ss z yyyy" but it fails with "unparsable Date"
What I know is: If I'd have "Sat Jan 24 00:00:00 GMT+1:00 2015", which is the same (right?), then my pattern works. But I can't (want..) modify it.
--> Is there a pattern which works out of the box, yes or no?
PS: I assume this question ends as duplicate of one of all the others, but if you vote so, please answer my bold question in addition, as I could not read it out of there with certainty
regards and thanks in advance
"Hours must be between 0 to 23 and Minutes must be between 00 to 59. For example, "GMT+10" and "GMT+0010" mean ten hours and ten minutes ahead of GMT, respectively."
as per java time zone specification http://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html and this is what i found for three letter time zone 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.
so i do not think there is any out of box pattern which works for you. check the other answer .
I don't think there is a pattern that can match your timezone / offset GMT+100. You could amend the input before parsing:
String input = "Sat Jan 24 00:00:00 GMT+100 2015";
input = input.replaceAll("([+-])(\\d+?)(\\d{2})", "$1$2:$3");
String pattern = "EEE MMM dd HH:mm:ss z yyyy";
Date date = new SimpleDateFormat(pattern, Locale.ENGLISH).parse(input);
I'm receiving a ParseException with the following code and I can't seem to fix it:
String date = "Tue Mar 13 2012 10:48:05 GMT-0400";
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zzzX"); //Tried zzzZ at the end as well
System.out.println(format.parse(date));
If I take out the -0400 and the X (or Z) at the end of the SimpleDateFormat things work fine, but once it's in the code, it simply doesn't work. What symbol should I be using instead? I'm using Java 7.
Here is the parse error I receive:
java.text.ParseException: Unparseable date: "Tue Mar 13 2012 10:48:05 GMT-0400"
at java.text.DateFormat.parse(DateFormat.java:357)
java.text.ParseException: Unparseable date: "Tue Mar 13 2012 10:48:05 GMT-0400"
at java.text.DateFormat.parse(DateFormat.java:357)
at com.throwaway.parse.DateParsing.testDate(TestDate:17)
The GMT part of GMT-0400 of your string is causing the problem.
The Z (or X in java 7) parameter is only matching -4000. You have to escape GMT by using single quotes like this :
DateFormat format = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.US);
Note that it's also a good practice to put a Local in your DateFormat. Without it your code won't work in other countries (like here in France...).
Three issues all dealing with mixed usage. Either:
Use a single lower-case "z" and a ":" separating your hour and time in the time zone when using "GMT(+/-)hh:mm", or
Use a single upper-case "Z" and drop the "GMT" from your timezone, and you can use the "(+/-)hhmm" format, or
Use a single upper-case "X" and still drop the "GMT" but you can use any format of the hhmm zone.
From the Javadoc:
z General time zone Pacific Standard Time; PST; GMT-08:00
Z RFC 822 time zone -0800
X ISO 8601 time zone -08; -0800; -08:00
The pattern zzzz could only parse "GMT-04:00" style strings. Your example can be parsed with this pattern: EEE MMM dd yyyy HH:mm:ss Z
use "EEE MMM dd yyyy HH:mm:ss zzzZ".
zzz is for GMT and Z is for 'RFC 822 time zone' please refer
Check this out
If you always expect your timezone to be represented that way, you could put "GMT" in single quotes in your format string to prevent it from being parsed:
EEE MMM dd yyyy HH:mm:ss 'GMT'XX
It's a bit weird that none of the built-in formats can parse it though. Perhaps the Javadoc is incorrect when it lists GMT-08:00 as an example of z?