Converting date to GMT - java

I want to convert a date to GMT.
I get a date in BST, I want to convert it to GMT without time zone conversion.
Example:
**If the BST date is: Wed June 26 13:30:13 BST 2019
I want to convert it to Wed 26 Jun 2019 13:30:13 GMT**
I want to ignore the timezone info and return the same date as GMT.
For this I am trying
private SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private SimpleDateFormat dateFormatGmtText = new SimpleDateFormat("EEE dd MMM yyyy HH:mm:ss 'GMT'");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
String textDate = dateFormatLocal.format(date);
//Date is Wed June 26 13:30:13 BST 2019
private Date toGMTDate(final Date date) {
String textDate = dateFormatLocal.format(date);
try {
String[] dateParts = textDate.split("\\+");
textDate = dateParts[0] + "+0000";
return dateFormatGmt.parse(textDate);
} catch (ParseException e) {
return null;
}
}
private String toGMT(final Date date) {
return dateFormatGmtText.format(toGMTDate(date));
}
When I call toGMT it returns Wed 26 Jun 2019 14:30:13 GMT
I am not sure why it is so?
What is wrong here?

java.time
You said you can’t use the modern date and time API, but for other readers I should like to present that option first. SimpleDateFormat and Date are poorly designed and long outdated, the former in particular notoriously troublesome, so I recommend avoiding them.
I am assuming that BST is for British Summer Time (other interpretations exist). And I am assuming that you cannot avoid getting an old-fashioned Date object.
private static DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("EEE dd MMM yyyy HH:mm:ss z", Locale.UK);
private static ZoneId britain = ZoneId.of("Europe/London");
private static ZoneId gmt = ZoneId.of("Etc/GMT");
private static String toGMT(final Date date) {
ZonedDateTime britishTime = date.toInstant().atZone(britain);
ZonedDateTime gmtTime = britishTime.withZoneSameLocal(gmt);
return gmtTime.format(formatter);
}
Try it out with your Date of Wed Jun 26 13:30:13 BST 2019:
String textDate = dateFormatLocal.format(date);
System.out.println(textDate);
System.out.println(toGMT(date));
Output is:
2019-06-26T13:30:13+0100
Wed 26 Jun 2019 13:30:13 GMT
Whenever you get an old-fashioned Date, the first thing to do is to convert it to Instant. Then do any further conversions from there. The key to changing time zone and keeping the date and time of day (hour-minute-second of day) is the withZoneSameLocal method of the ZonedDateTime class.
I recommend specifying locale for the formatter.
I am not sure why it is so? What is wrong here?
A Date hasn’t got, as in cannot have a time zone. It’s a point in time, nothing more. YourtoGMTDate method returns a point in time that is an hour later: The time you gave it was 13:30:13+0100, and it returned 13:30:13+0000, which is the same point in time as 14:30:13+0100. Next you formatted this point in time using a formatter that used your default time zone, Europe/London, and therefore produced 14:30:13, but at the same time printed GMT in the string — the result you reported.
…the new time library, but for some reasons I can't use them.
If you really have got an evil boss that either forces you to use Java 1.4 or 1.5 and/or forbids the use external dependencies, the pretty simple hack is:
private String toGMT(final Date date) {
return dateFormatGmtText.format(date);
}
The cheating is: Your dateFormatGmtText uses your default time zone, Europe/London, but lies and prints GMT in the formatted string. This gives the same output as above — the output you asked for. Compared to your code I am just leaving out the date conversion.
Link: Oracle tutorial: Date Time explaining how to use java.time.

Related

Time in milliseconds when Timezone set as UTC from program

My computer timezone is IST and I m executing the following code
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
SimpleDateFormat format1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
long millisFromDate = format1.parse("Tue, 22 Jun 2021 15:40:52 IST").getTime();
System.out.println(millisFromDate);
The above snippet prints 1624369252000.
Now when I convert 1624369252000
UTC time & date: Tue Jun 22 2021 13:40:52 in https://currentmillis.com/
I think I am doing something wrong. Can any one help?
It should have been 10:10:52 in UTC?
Use java.time to specify what you mean by IST
I always recommend that you use java.time, the modern Java date and time API, for your date and time work.
Three letter time zone abbreviations like IST are very often, possibly most often ambiguous, so also very often give you different results from what you had expected. I suspect that this is also what happened in your case.
java.time gives us the opportunity to specify one or more preferred time zones in case of an ambiguous abbreviation. For example:
private static final Set<ZoneId> PREFERRED_ZONE = Set.of(ZoneId.of("Atlantic/Reykjavik"));
private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("EEE, dd MMM yyyy HH:mm:ss ")
.appendZoneText(TextStyle.SHORT, PREFERRED_ZONE)
.toFormatter(Locale.ROOT);
To use:
String dateTimeString = "Tue, 22 Jun 2021 15:40:52 IST";
ZonedDateTime zdt = ZonedDateTime.parse(dateTimeString, FORMATTER);
System.out.println(zdt);
long millisFromDate = zdt.toInstant().toEpochMilli();
System.out.println(millisFromDate);
Output in this case:
2021-06-22T15:40:52Z[Atlantic/Reykjavik]
1624376452000
So just fill in the time zone ID that you intended in the first line. Other examples:
private static final Set<ZoneId> PREFERRED_ZONE = Set.of(ZoneId.of("Europe/Dublin"));
2021-06-22T15:40:52+01:00[Europe/Dublin]
1624372852000
private static final Set<ZoneId> PREFERRED_ZONE = Set.of(ZoneId.of("Asia/Tel_Aviv"));
2021-06-22T15:40:52+03:00[Asia/Tel_Aviv]
1624365652000
You had expected a result equivalent to 10:10:52 UTC. That you get from the following:
private static final Set<ZoneId> PREFERRED_ZONE = Set.of(ZoneId.of("Asia/Kolkata"));
2021-06-22T15:40:52+05:30[Asia/Kolkata]
1624356652000
A preferred zone of Asia/Colombo gives the same result.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Time Zone Abbreviations – Worldwide List

Wrong value while converting UTC date to a given timezone

I am trying to convert a UTC date String of the format 2020-06-09T06:30:00Z to a Timezone like Asia/Calcutta.
The time offset between UTC and Asia/Calcutta is +5:30, so the expected result on converting 2020-06-09T06:30:00Z to Asia/Calcutta is 2020-06-09T12:00:00Z but I am getting 2020-06-09T01:00:00Z
String utcDate = "2020-06-09T06:30:00Z";
String timezone = "Asia/Calcutta";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
LocalDateTime date = LocalDateTime.parse(utcDate, formatter); //2020-06-09T06:30
ZonedDateTime zonedDate = ZonedDateTime.of(date, ZoneId.of(timezone)); //2020-06-09T06:30+05:30[Asia/Calcutta]
Date dateConverted = Date.from( zonedDate.toInstant()); //Tue Jun 09 01:00:00 UTC 2020
I think zonedDate.toInstant() is converting subtracting 5:30 instead of adding 5:30 to 2020-06-09T06:30. My machine is in UTC timezone. may be its converting to local time don't know what is the issue. Also tried below method, still same issue.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone(timezone));
sdf.parse(dateString);
java.time
I agree with you, you should strongly prefer to use java.time, the modern Java date and time API. It’s not complicated when you know how.
String utcDate = "2020-06-09T06:30:00Z";
String timezone = "Asia/Calcutta";
ZoneId zone = ZoneId.of(timezone);
ZonedDateTime zdt = Instant.parse(utcDate).atZone(zone);
System.out.println("zdt: " + zdt);
Output is:
zdt: 2020-06-09T12:00+05:30[Asia/Calcutta]
You notice that the time of day in the ZonedDateTime is 12:00 as you had expected. The trailing Z that you also said you expected is wrong, though. Z means an offset of 0 from UTC, so since the offset is +05:30, we are very happy not to have the Z there.
If what you needed was an old-fashioned Date object, presumably for a legacy API that you don’t want to upgrade just now, there’s no reason to convert to your time zone first. This works:
Date oldfashionedDate = Date.from(Instant.parse(utcDate));
System.out.println("oldfashionedDate: " + oldfashionedDate);
Output in my time zone is:
oldfashionedDate: Tue Jun 09 08:30:00 CEST 2020
You may be in doubt whether the Date is right. It is. Since I am in Europe/Copenhagen time zone, currently at offset +02:00, the Date prints in this time zone, so the time of day is 8:30 (the Date doesn’t hold a time zone or offset). If instead I run in Asia/Calcutta time zone:
oldfashionedDate: Tue Jun 09 12:00:00 IST 2020
You notice IST for India Standard Time instead of CEST for Central European Summer Time. And the time is 12:00 as expected.
Points for you to take with you
Never hardcode Z as a literal in a format pattern string. As I said, it’s an offset, so it needs to be parsed as an offset.
For the same reason don’t parse into a LocalDateTime. A LocalDateTime. hasn’t got any offset, so you are losing information.
In this case use no formatter at all. Your format is ISO 8601, and Instant parses it as its default, that is, without any explicit formatter (OffsetDateTime and ZonedDateTime do too).
Make the conversion from UTC to Asia/Calcutta. It seems to me that you were doing the opposite conversion.
Link
Wikipedia article: ISO 8601
Got it work using SimpleDateFormat as shown below. But anyone coming across this issue should probably use ZonedDateTime.
String utcDate = "2020-06-09T06:30:00Z";
String timezone = "Asia/Calcutta";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf1.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = sdf1.parse(utcDate); // Tue Jun 09 06:30:00 UTC 2020
SimpleDateFormat sdf2 = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
sdf2.setTimeZone(TimeZone.getTimeZone(timezone));
String sDateInZone = sdf2.format(date); // 09-6-2020 12:00:00 PM
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
Date dateInZone = formatter.parse(sDateInZone); // Tue Jun 09 12:00:00 UTC 2020
EDIT: Got it to work using ZonedDateTime also as shown below:
String utcDate = "2020-06-09T06:30:00Z";
String timezone = "Asia/Calcutta";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
LocalDateTime dateUtc = LocalDateTime.parse(utcDate, formatter);
ZonedDateTime utcZonedDateTime = dateUtc.atZone(ZoneId.systemDefault());
ZoneId zoneId = ZoneId.of(timezone);
ZonedDateTime zonedDateTime = utcZonedDateTime.withZoneSameInstant(zoneId);
String zoneDateString = formatter.format(zonedDateTime);
Date date = Date.from(LocalDateTime.parse(zoneDateString, formatter).atZone(ZoneId.systemDefault()).toInstant());

How to convert a time to UTC and then device local time

I am getting following time from service
'Nov 11 2019 7:30 PM'
I know this is US Central Time, I need to get hours between current time and this event time, but i am unable to understand how to convert this date to UTC.
I am using following approach, but this does not seem to be working fine.
public Date ticketJSONDateFormatter(String dateTime){
SimpleDateFormat simpleDateFormatter
= new SimpleDateFormat("MMM d yyyy HH:mm a");
Date parsedDate = null;
try {
simpleDateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
parsedDate = simpleDateFormatter.parse(dateTime);
} catch (ParseException e) {
e.printStackTrace();
}
return parsedDate;
}
This method returns following date
Fri Oct 11 12:30:00 GMT+05:00 2019
Although the expected output may be something like this. My device is at (+5:00 UTC)
Fri Oct 12 12:30:00 GMT+05:00 2019
You can use `LocalDateTime' to parse the string to date,
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm a");
String date = "Nov 11 2019 07:30 PM";
LocalDateTime ldt = LocalDateTime.parse(date, formatter);
Then convert it to your preferred zone,
Instant cdt = ldt.atZone(ZoneId.of("America/Chicago")).toInstant();
return cdt.atOffset(ZoneOffset.UTC)
This will return an Instant.
And as Ole V.V suggested in the comment, I wouldn't recommend using old Date and Calendar API. I would suggest reading this answer to understand the issues associated with the old Date API.
You can get this in following steps:
Use ZonedDateTime.parse to parse the time you are receiving.
Convert the America Central time to your local time.
Get your current time.
Find the difference between your current time and the event time converted to your local.
Example:
// Parsing the time you are receiving in Central Time Zone. Using Chicago as a representative Zone.
String dateWithZone = "Nov 11 2019 7:30 PM".concat("America/Chicago") ;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd uuuu h:m aVV");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateWithZone, formatter);
System.out.println(zonedDateTime); // This is the time you received in Central time zone.
// Now convert the event time in your local time zone
ZonedDateTime eventTimeInLocal = zonedDateTime.withZoneSameInstant(ZoneId.systemDefault());
// Then find the duration between your current time and event time
System.out.println(Duration.between(ZonedDateTime.now(), eventTimeInLocal).toHours());
The duration class provides many other utilities methods to get more precise duration.

Convert String in EST to Date in PST

I tried the below approach and searched in Web to find the solution for this but no luck : looking for the solution for converting a String in IST to PST:
String string = new Date().toString();
System.out.println(string);
SimpleDateFormat dt = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
dt.setTimeZone(TimeZone.getTimeZone("PST"));
Date D = dt.parse(string);
System.out.println(""+ D);
Even when I set time zone as PST, I am seeing out put in IST
here is the out put:
Tue Apr 18 18:58:09 IST 2017
Tue Apr 18 18:58:09 IST 2017
I tried another Option here I am seeing even it is showing the time in PST but I see below output it is a bit confusing:
public static Date convertFromOneTimeZoneToOhter(Date dt,String from,String to ) {
TimeZone fromTimezone =TimeZone.getTimeZone(from);//get Timezone object
TimeZone toTimezone=TimeZone.getTimeZone(to);
long fromOffset = fromTimezone.getOffset(dt.getTime());//get offset
long toOffset = toTimezone.getOffset(dt.getTime());
//calculate offset difference and calculate the actual time
long convertedTime = dt.getTime() - (fromOffset - toOffset);
Date d2 = new Date(convertedTime);
return d2;
}
OUT PUT:
Converted Date : Tue Apr 18 06:28:09 IST 2017
Can someone please help on this: I found lot of solutions on converting IST Date time to PST String but not IST/EST Date to PST Date.
As I mentioned above we can format to a String, but I am looking for an example of converting back to Date
You should look into Java 8's new Date API that handles timezones directly
// Get the current date and time
ZonedDateTime date1 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]");
System.out.println("date1: " + date1);
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println("Zoned Date Time: " + zonedDateTime);
ZoneId id = ZoneId.of("Europe/Paris");
System.out.println("ZoneId: " + id);
ZoneId currentZone = ZoneId.systemDefault();
System.out.println("CurrentZone: " + currentZone);
Prints :
date1: 2007-12-03T10:15:30+05:00[Asia/Karachi]
Zoned Date Time: 2017-04-18T09:52:09.045-04:00[America/New_York]
ZoneId: Europe/Paris
CurrentZone: America/New_York
Since some readers here will use Java 8 or later and some Java 7 or earlier, I will treat both.
I recommend you use the java.time classes introduced in Java 8 if you can:
ZoneId targetTz = ZoneId.of("America/Los_Angeles");
String string = "Tue Apr 18 18:58:09 +0300 2017";
DateTimeFormatter format = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss ZZZ uuuu",
Locale.ENGLISH);
ZonedDateTime sourceTime = ZonedDateTime.parse(string, format);
ZonedDateTime targetTime = sourceTime.withZoneSameInstant(targetTz);
String result = targetTime.format(format);
System.out.println(result);
This prints:
Tue Apr 18 08:58:09 -0700 2017
You said you wanted a PST date, and this is exactly what the ZonedDateTime gives you: date and time with time zone information.
In the example I am giving a zone offset, +0300 (corresponding to Israel Daylight Time) in the string. I understood that it wasn’t important to you how the time zone was given. I want to avoid the three and four letter time zone abbreviations like IST. Not only may IST mean either Irish Standard Time, Israel Standard Time or India Standard Time. I furthermore noticed that the java.time classes pick up 18:58:09 IST as 18:58:09 IDT (UTC+3) because it knows Israel is on DST on April 18; the SimpleDateFormat that I return to below takes IST more literally and interprets 18:58:09 IST as 18:58:09 +0200, which is 1 hour later in UTC.
You can use the java.time classes with Java 1.7 if you want. You can get them in the ThreeTen Backport.
If you don’t want to use java.time, the way to do it with the outdated classes from Java 1.0 and 1.1 is not that different in this case, only I cannot give you the PST date you asked for:
TimeZone targetTz = TimeZone.getTimeZone("America/Los_Angeles");
String string = "Tue Apr 18 18:58:09 +0300 2017";
SimpleDateFormat dt = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy", Locale.ENGLISH);
Date d = dt.parse(string);
dt.setTimeZone(targetTz);
String result = dt.format(d);
System.out.println(result);
It prints the same result as above. However, you notice there is only one Date object. A Date object cannot hold any time zone information, so if you need this, you will have to bring the targetTz object along with d. It’s a common misunderstanding that there’s supposed to be a time zone in the Date object, probably greatly helped by the fact that its toString() prints a time zone. This is always the JVM’s default time zone and doesn’t come from the Date object, though.

Convert Date Time String from one timezone A to timezone B where jvm is running in timezone C

I have a scenario where I need to convert a date time string from Timezone A(UTC) to Timezone B(EST).
Catch here is the JVM where this transformation is happening is Timezone C(HKT) Date Object.
So the code block is as follows:
String dateString="20141114213000";
dateString += " UTC";
String formatString ="yyyyMMddHHmmss";
SimpleDateFormat sdf = new SimpleDateFormat(formatString + " z");
Date localDate = sdf.parse(dateString);
System.out.println("Local Date::"+localDate); // Local Date::Sat Nov 15 05:30:00 HKT 2014
Calendar localCal = Calendar.getInstance();
localCal.setTime(localDate);
TimeZone estTimeZone = TimeZone.getTimeZone("America/New_York");
localCal.setTimeZone(estTimeZone);
sdf.setTimeZone(estTimeZone);
System.out.println(sdf.format(localCal.getTime()));//20141114163000 EST
System.out.println(localCal.getTime());//Sat Nov 15 05:30:00 HKT 2014
The output I am expecting is to be "Fri Nov 14 16:30:00 EST 2014" from the last statement, i.e., the final date object available should be in EST.
Please let know if anyone has info on this.
Update:
Just to make my request clear, output should be in Date object only.
The sample code and the output I printed is only for clearer explanation.
So basically String "20141114213000" which is a UTC Date String needs to be converted to EST Date Object and JVM where this transformation is happening is in HKT.
There seems to be notable issues with Java's Date and Time classes.
Lets use the popular Joda-Time - Java date and time API.
Simply download the newest stable release and add the jar files to your project's build path.
On a line-by-line basis, I have commented out your code and rewritten the Joda Time alternative. This way you can understand how I transitioned your existing code to the Joda Time API.
import java.text.ParseException;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class JodaTimeTransition {
public static void main(String[] args) throws ParseException {
String dateString="20141114213000";
dateString += " UTC";
/*new*/
String formatString = "yyyyMMddHHmmss z";
// String formatString ="yyyyMMddHHmmss";
/*new*/
DateTimeFormatter dtf = DateTimeFormat.forPattern(formatString);
// SimpleDateFormat sdf = new SimpleDateFormat(formatString + " z");
/* new - Create localDate using JodaTime DateTime class */
DateTime localDate = DateTime.parse(dateString, dtf);
// Date localDate = sdf.parse(dateString);
/* new - convert time to MST, since it is currently UTC*/
localDate = localDate.toDateTime(DateTimeZone.forID("America/Denver"));
/* new - print out <local date> using specified format.*/
System.out.println("Local Date::" + localDate.toString("EEE MMM dd HH:mm:ss z yyyy"));
/* Where did you get the local date mentioned at comments of line below? */
// System.out.println("Local Date::"+localDate); // Local Date::Sat Nov 15 05:30:00 HKT 2014
/* new - Get reference to current date/time as <localCal>
* (This step can be omitted, and the previous localDate variable can be used)
*/
DateTime localCal = DateTime.now();
// Calendar localCal = Calendar.getInstance();
/* new - Set <localCal> to <localDate> */
localCal = localDate;
// localCal.setTime(localDate);
/* new - Create new EST time zone*/
DateTimeZone estTimeZone= DateTimeZone.forID("America/New_York");
// TimeZone estTimeZone = TimeZone.getTimeZone("America/New_York");
/* new - set <localCal> time zone from MST to EST */
localCal = localCal.toDateTime(estTimeZone);
// localCal.setTimeZone(estTimeZone);
// sdf.setTimeZone(estTimeZone);
/* new - print <localCal> as new EST time zone */
System.out.println(localCal.toString("yyyyMMddHHmmss z"));
// System.out.println(sdf.format(localCal.getTime()));//20141114163000 EST
/* new - print in desired format: Fri Nov 14 16:30:00 EST 2014 */
System.out.println(localCal.toString("EEE MMM dd HH:mm:ss z yyyy"));
// System.out.println(localCal.getTime());//Sat Nov 15 05:30:00 HKT 2014
}
}
This is actually very straightforward (no need for Joda time, not that it isn't a great library), you just need to set the TimeZone on the SimpleDateFormat. Use the source TimeZone when you parse, then the destination TimeZone when you format (and you don't need the intermediate Calendar).
UPDATE:
Date's don't have TimeZones. If you want something with a TimeZone (other than a String), then you will need a Calendar. Your current code is mostly correct except that you haven't set the source TimeZone on the SimpleDateFormat before parsing.
Update
After some discussion in the comments, it seems now clear that you should not rely on java.util.Date for time zones at all. The trick sketched below (my original answer) will probably work, but it is not the right thing to do. Switch to something which supports time zones (java.util.Calendar for instance), but better use JodaTime.
Warning: this is a trick which may (or may not) work for Sun's implementation of java.util.Date whose internal structures are initialized with a time zone.
Try setting the default time zone with TimeZone.setDefault(...) first.
Your last call:
System.out.println(localCal.getTime());
Is actually:
System.out.println(new Date(localCal.getTimeInMillis()).toString());
So setting any time zone info on the calendar is pointless.
Date.toString(), however first does an internal normalization on the date and uses the static TimeZone.getDefaultRef(). This should give you the default time zone - which you can (normally) set via TimeZone.setDefailt(...).
And by all means use JodaTime.

Categories

Resources