Preserve Timezone while parsing a string to date in java - java

While parsing String "Sat Mar 2 09:40:20 PST 2019", it is getting converted to IST. How can I preserve the timezone while parsing the string to a date.

This could be done using standard Java time library and ZonedDateTime class. Take a look at following example how to do it:
String date = "Sat Mar 2 09:40:20 PST 2019";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss zzz yyyy", Locale.ENGLISH);
ZonedDateTime zonedDateTime = ZonedDateTime.parse(date,formatter);
System.out.println(zonedDateTime);

Create a Key/Value pair of all global timezones and their GMT offset, then you can reconvert the times from there. Here's a list: https://publib.boulder.ibm.com/tividd/td/TWS/SC32-1274-02/en_US/HTML/SRF_mst273.htm

Related

Java parse date from string with GMT string

I have the following date string Tue Feb 04 2020 16:11:25 GMT+0200 (IST) where I'm trying to convert into date time using the following code:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM d yyyy HH:mm:ss O (zzz)", Locale.ENGLISH);
LocalDate dateTime = LocalDate.parse("Tue Feb 04 2020 16:11:25 GMT+0200 (IST)", formatter);
And I got the following exception:
Text Tue Feb 04 2020 16:11:25 GMT+0200 (IST) could not be parsed at index 28
I look at the following SO question Java string to date conversion and I see that
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
So why I got the exception?
The following pattern works.
"E MMM d u H:m:s 'GMT'Z (z)"
You can replace Z with x or X for the same result.
You can spell it out, if you want, but it is not necessary.
"EEE MMM dd uuuu HH:mm:ss 'GMT'ZZZ (zzz)"
You should parse that input to an OffsetDateTime, since the input string includes a Date, a Time, and an Offset.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E MMM d u H:m:s 'GMT'Z (z)", Locale.ENGLISH);
OffsetDateTime dateTime = OffsetDateTime.parse("Tue Feb 04 2020 16:11:25 GMT+0200 (IST)", formatter);
System.out.println(dateTime);
Output
2020-02-04T16:11:25+02:00
One of the reasons is that you are trying to parse a datetime String (date, time, zone and offset) to an object (LocalDate) that only stores year, month and day, nothing more.
Use a suitable class, say ZonedDateTime and adjust the parsing pattern a little:
you can't use the localized offset O because in a DateTimeFormatter it doesn't support the formatting your String has, which is GMT+0200 and the formatter supports GMT+8; GMT+08:00; UTC-08:00; only (mind the colon). Use a combination of an escaped GMT plus a regular offset symbol x
you have a single d but a representation of days that will always have two digits, so you need to use dd
you have to escape the brackets the zone abbreviation is enclosed in and I think a single z is sufficient for such an abbreviation
Considering all these aspects, you could parse the String as follows:
public static void main(String[] args) {
String parsePattern = "EEE MMM dd yyyy HH:mm:ss 'GMT'x '('z')'";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(parsePattern,
Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse("Tue Feb 04 2020 16:11:25 GMT+0200 (IST)", formatter);
System.out.println(zdt);
}
which then outputs (using the default formatter for ZonedDateTime)
2020-02-04T16:11:25+02:00[Asia/Jerusalem]
The problem here is the GMT+0200 if you use: GMT+02 it works.
But as already mentioned in the comments it is a little confusing that you use a variable called dateTime on something of the type LocalDate.
So your result will be only the date 2020-02-04 because LocalDate can only save this kind of data.
2 things - ZonedDateTime & missing ':' for 0
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss O (zzz)");
ZonedDateTime dateTime = ZonedDateTime.parse("Tue Feb 04 2020 16:11:25 GMT+02:00 (IST)", formatter);
This should work
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM d yyyy HH:mm:ss 'GMT'Z (z)", Locale.ENGLISH);
LocalDate dateTime = LocalDate.parse("Tue Feb 04 2020 16:11:25 GMT+0200 (IST)", formatter);
Do not use a fixed text for the timezone:
Do not use a fixed text (e.g. 'GMT') for the timezone as mentioned in the existing answers because that approach may fail for other locales.
The recommended solution:
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 Feb 04 2020 16:11:25 GMT+0200 (IST)";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM d u H:m:s VVZ (z)", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
2020-02-04T14:11:25Z[Atlantic/Reykjavik]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
you wrote one d and you passed 04 you should write dd instead of d like the following
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss O (zzz)", Locale.ENGLISH);
LocalDate dateTime = LocalDate.parse("Tue Feb 04 2020 16:11:25 GMT+0200 (IST)", formatter);

How to compare the datetime of format "EEE MMM dd HH:mm:ss zzz yyyy" and "yyyy-MM-dd hh:mm:sss" in java?

I have date of type "EEE MM DD HH:mm:ss zzz yyyy" (Wed Mar 04 03:34:45 GMT+08:00 2020) and "yyyy-MM-dd hh:mm:ss" (2020-02-04 02:10:58).How to compare this two date in java?
Both dates are in same timezone.
If you assume that the timezone of the second date is the same as for the first one then you can just use java.time. It has all parsing tools you need. Any other fixed timezone works as well.
Here is an example:
String a = "Wed Mar 04 03:34:45 GMT+08:00 2020";
String b = "2020-02-04 02:10:58";
ZonedDateTime parsedA;
ZonedDateTime parsedB;
DateTimeFormatter formatterA = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy");
parsedA = ZonedDateTime.parse(a, formatterA);
DateTimeFormatter formatterB = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
parsedB = LocalDateTime.parse(b, formatterB).atZone(parsedA.getZone());
// What do you want to compare? For example you can tell if a is after b.
System.out.println(parsedA.isAfter(parsedB));
Have a look here if you need another format and need a listing of Pattern Letters and Symbols.
First of all these two dates are not comparable because of missing timezone in the second date.
Secondly, If you still want to do that with system's default time zone then you need to bring both the dates into common format.
Parse the dates into Date object and then you can play around it:
DateFormat dateFormat1 = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
Date date1 = dateFormat1.parse("Wed Mar 04 03:34:45 GMT+08:00 2020");
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date2 = dateFormat2.parse("2020-02-04 02:10:58");
System.out.println(date1.after(date2));
There is a difference between time zone and time zone offset. The Date-Time string Wed Mar 04 03:34:45 GMT+08:00 2020 has a time zone offset, not a time zone. A time zone is unique and therefore it has an ID e.g. ZoneId.of("America/New_York") whereas a time zone offset tells you about the amount of time by which a given time is offset from the UTC time. There can be many time zones falling on the same time zone offset. Check List of tz database time zones to learn more about it. So, the most appropriate type to parse Wed Mar 04 03:34:45 GMT+08:00 2020 into is OffsetDateTime.
Since the second Date-Time string 2020-02-04 02:10:58 has neither a time zone nor a time zone offset, parse it into LocalDateTime.
Make sure to use Locale with the formatter because Date-Time parsing/formatting API is Locale-sensitive.
As long as the second Date-Time string refers to a Date-Time at the same timezone offset (i.e. GMT+08:00), you can do either of the two to compare them
Convert the first Date-Time string into LocalDateTime after parsing and then compare it with the second Date-Time string parsed into a LocalDateTime.
Convert the second Date-Time string into an OffsetDateTime after parsing and then compare it with the first Date-Time string parsed into an OffsetDateTime.
I would prefer the first approach as it is simpler. However, for the sake of completeness, I've shown below both approaches.
First approach:
DateTimeFormatter odtFormatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O uuuu", Locale.ENGLISH);
OffsetDateTime firstOffsetDateTime = OffsetDateTime.parse("Wed Mar 04 03:34:45 GMT+08:00 2020", odtFormatter);
LocalDateTime firstLocalDateTime = firstOffsetDateTime.toLocalDateTime();
DateTimeFormatter ldtFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime secondLocalDateTime = LocalDateTime.parse("2020-02-04 02:10:58", ldtFormatter);
// Compare the two LocalDateTime values using isBefore, isAfter, equals etc.
if (firstLocalDateTime.isBefore(secondLocalDateTime)) {
// ...
}
Second approach:
DateTimeFormatter odtFormatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O uuuu", Locale.ENGLISH);
OffsetDateTime firstOffsetDateTime = OffsetDateTime.parse("Wed Mar 04 03:34:45 GMT+08:00 2020", odtFormatter);
DateTimeFormatter ldtFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime secondLocalDateTime = LocalDateTime.parse("2020-02-04 02:10:58", ldtFormatter);
OffsetDateTime secondOffsetDateTime = secondLocalDateTime.atOffset(firstOffsetDateTime.getOffset());
// Compare the two OffsetDateTime values using isBefore, isAfter, equals etc.
if (firstOffsetDateTime.isBefore(secondOffsetDateTime)) {
// ...
}
I also prefer u to y with a DateTimeFormatter.
Learn more about the the modern date-time API from Trail: Date Time.

Joda date formatter

Does anyone know how to parse a date such as: Mon Aug 04 16:07:00 CEST 2014
to dd/MM/YYYY HH:MM:SS using DateTime formatter from Joda.
I've tried that:
final DateTimeFormatter sdf = DateTimeFormat.forPattern(DATE_FORMAT);
DateTime lastDateOnline = sdf.parseDateTime(lastCommunicationToDisplay.getDateOnLine().toString());
return lastDateOnline.toString();
DATE_FORMAT = dd/MM/YYYY HH:MM:SS and
lastCommunicationToDisplay.getDateOnLine().toString() = Mon Aug 04 16:07:00 CEST 2014
I can't find clear explanations about that library. I'm requested to use that instead of SimpleDateFormat because it's not threadsafe.
Solutions
If all you have to do is convert a LocalDate to a string respecting the pattern: "dd/MM/YYYY HH:mm:ss", then you can do it in a simpler way, using the overloaded toString() methods on LocalDate:
a) the one which receives the format string directly:
LocalDate date = lastCommunicationToDisplay.getDateOnLine();
System.out.println(date.toString("dd/MM/YYYY HH:mm:ss"));
b) the one which receives a DateTimeFormatter initialized with the aforementioned string:
DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/YYYY HH:mm:ss");
LocalDate date = lastCommunicationToDisplay.getDateOnLine();
System.out.println(date.toString(dtf));
What went wrong in your code
The format string you are using is not compatible with the date string you are sending as input. The way you used DateTimeFormatter is used for parsing strings that are in that format to LocalDates, not the other way around.
The format would be appropriate if your input string would look like the following:
04/08/2014 22:44:33
Since yours looks differently, the following value of the format is compatible (provided your timezone is always CEST):
DATE_FORMAT = "E MMM dd HH:mm:ss 'CEST' YYYY";
So the entire code should look like this:
String dateString = "Mon Aug 04 16:07:00 CEST 2014";
DateTimeFormatter dtf = DateTimeFormat.forPattern("E MMM dd HH:mm:ss 'CEST' YYYY");
LocalDate date = dtf.parseLocalDate(dateString);
System.out.println(date.toString("MM/dd/yyyy")); // or use toString(DateTimeFormatter) and use your pattern with a small adjusment here (dd/MM/YYYY HH:mm:ss)
However, I recommend one of the first 2 suggestions.

Convert date to other format in JodaTime

I've a problem to convert a data in Java using Joda-Time library.
Pratically, the input date have this format:
Mon Apr 28 18:57:42 CEST 2014
I would like to see this output:
2014-04-28
I've tried this code, but doesn't works:
DateTimeFormatter dtf_out = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTimeFormatter dtf_inp = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zzz yyyy");
String a = String.valueOf(dtf_inp.parseDateTime(String.valueOf(resultsJs.get(0).getTimestamp()))); //crash here
String b = String.valueOf(dtf_out.parseDateTime(a));
Note: resultsJs.get(0).getTimestamp() is a Date format.
Instead, this is the log:
...
Caused by: java.lang.IllegalArgumentException: Invalid format: "Mon Apr 28 18:57:42 CEST 2014"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:873)
...
You are trying to parse an epoch millisecond value, but you can only parse a String.
However, it seems you already have a millisecond value available, so only the formatting is required, which is via the print() method:
DateTimeFormatter dtf_out = DateTimeFormat.forPattern("yyyy-MM-dd");
String b = dtf_out.print(resultsJs.get(0).getTimestamp().getTime());
Its working fine after removing timezone info from the actual string but I have used time zone while parsing hence it will give you the correct result based on locale.
Please validate the result.
// pattern zzz is removed that is used for parsing time zone
DateTimeFormatter dtf_inp = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss yyyy");
// time zone is added while parsing date time
DateTime dateTime = dtf_inp.withZone(DateTimeZone.forID("Europe/Paris"))
.parseDateTime("Mon Apr 28 18:57:42 2014");
// simply call toString(pattern) on DateTime
System.out.println(dateTime.toString("yyyy-MM-dd")); // 2014-04-28
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String output = sdf.format(yourDate);

Parse a String to Date in Java

I'm trying to parse a string to a date, this is what I have:
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ (zzzz)");
Date date = new Date();
try {
date = sdf.parse(time);
} catch (ParseException e) {
e.printStackTrace();
}
the string to parse is this:
Sun Jul 15 2012 12:22:00 GMT+0300 (FLE Daylight Time)
I followed the http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Pretty sure I've done everything by the book. But it is giving me ParseException.
java.text.ParseException: Unparseable date:
"Sun Jul 15 2012 12:22:00 GMT+0300 (FLE Daylight Time)"
What am I doing wrong? Patterns I Have tried:
EEE MMM dd yyyy HH:mm:ss zzz
EEE MMM dd yyyy HH:mm:ss zZ (zzzz)
You seem to be mixing the patterns for z and Z. If you ignore the (FLE Daylight Time), since this is the same info as in GMT+0300, the problem becomes that SimpleDateFormat wants either GMT +0300 or GMT+03:00. The last variant can be parsed like this:
String time = "Sun Jul 15 2012 12:22:00 GMT+03:00 (FLE Daylight Time)";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zzz");
Date date = sdf.parse(time);
[EDIT]
In light of the other posts about their time strings working, this is probably because your time string contains conflicting information or mixed formats.
java.time
I should like to contribute the modern answer. Use java.time, the modern Java date and time API, for your date and time work.
First define a formatter for parsing:
private static final DateTimeFormatter PARSER = DateTimeFormatter
.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z (", Locale.ROOT);
Then parse in this way:
String time = "Sun Jul 15 2012 12:22:00 GMT+0300 (FLE Daylight Time)";
TemporalAccessor parsed = PARSER.parse(time, new ParsePosition(0));
OffsetDateTime dateTime = OffsetDateTime.from(parsed);
System.out.println(dateTime);
Output is:
2012-07-15T12:22+03:00
I am not parsing your entire string, but enough to establish a point in time and an offset from GMT (or UTC). Java cannot parse the time zone name FLE Daylight Time. This is a Microsoft invention that Java does not know. So I parse up to the round bracket before FLE in order to validate this much of the string. To instruct the DateTimeFormatter that it needs not parse the entire string I use the overloaded parse method that takes a ParsePosition as second argument.
From Wikipedia:
Sometimes, due to its use on Microsoft Windows, FLE Standard Time (for
Finland, Lithuania, Estonia, or sometimes Finland, Latvia, Estonia) …
are used to refer to Eastern European Time.
If you indispensably need a Date object, typically for a legacy API that you cannot afford to upgrade to java.time just now, convert like this:
Date oldfashionedDate = Date.from(dateTime.toInstant());
System.out.println(oldfashionedDate);
Output when run in Europe/Tallinn time zone:
Sun Jul 15 12:22:00 EEST 2012
What went wrong in your code?
Your SimpleDateFormat successfully parsed GMT+03 into a “time zone” matching the small z in the format pattern string. It then tried to parse the remaining 00 into an offset to match the capital Z. Since an offset requires a sign, this failed.
What am I doing wrong?
As others have said, you should not try to parse GMT into a time zone abbreviation. GMT can be used as a time zone abbreviation; but your time is not in GMT. So you don’t want that. It would only be misleading. Had you been successful, you would rather have risked an incorrect result because you had parsed a time zone that was incorrect for your purpose.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Eastern European Time on Wikipedia.
Try it this way..
System.out.println(new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zZ (zzzz)").format(new Date()));
Output i got:
Thu Jul 12 2012 12:41:35 IST+0530 (India Standard Time)
You can try to print the date format string :
/**
* #param args
*/
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zZ (zzzz)");
Date date = new Date();
try {
//
System.out.println(sdf.format(date));
date = sdf.parse(time);
} catch (Exception e) {
e.printStackTrace();
}
}
If you have problems with locales, you can either set the default Locale for the whole application
Locale.setDefault(Locale.ENGLISH);
or just use the english locale on your SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss zZ (zzzz)", Locale.ENGLISH);
You can also use Locale.US or Locale.UK.

Categories

Resources