I am converting time from GMT to different USA time-zones. For that, I have written a method which is returning the 1-hour prior time. if the time is 2:00 clock it's returning 1:00 clock
private static Date timeFormat(String timeZone) throws ParseException {
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateFormat gmtFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
gmtFormat.setTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getID()));
Date date = null;
try {
date = gmtFormat.parse(sdfDate.format(new Date()));
LOG.info("GMT format time and date ==>> "+date);
} catch (ParseException e) {
e.printStackTrace();
}
DateFormat pstFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
pstFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
String timedd = pstFormat.format(date);
LOG.info("Return the new time based on timezone : "+pstFormat.format(date));
return gmtFormat.parse(timedd);
}
Can anybody help me out what exactly is the issue, because a few months back the same method was working fine? Is it happening because of daylight saving time?
This can be done in a much simpler way using java.time APIs. Use Instant to represent the time in UTC. It can be converted to time at any zone, and formatted to a particular pattern.
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Instant now = Instant.now();
ZonedDateTime dt = now.atZone(ZoneId.of("UTC-05:00"));
System.out.println(dt.format(format)); //2017-05-24 04:51:03
ZonedDateTime pstDate = now.atZone(ZoneId.of("UTC-07:00"));
System.out.println(pstDate.format(format)); //2017-05-24 02:51:03
After so much of digging i have found that TimeZone won't give correct result on basis of time-zone
(EST, CST, MST, PST)
so in my method the param which i have passed as timeZone was coming as a
(EST, CST, MST, PST)
Instead of EST, CST, MST, PST i have passed US/Eastern US/Pacific US/Mountain US/Central, and it worked fine for me
Related
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.
The data I fetch from DB is in UTC time. I need to convert it to CET/CEST. I am using below code. I am not sure if both CET and CEST will be taken care of. Please let me know if it takes care of CET and CEST ?
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
return LocalDateTime.parse(ptu, formatter)
.atOffset(ZoneOffset.UTC)
.atZoneSameInstant(ZoneId.of("Europe/Amsterdam"))
.format(formatter);
CET and CEST are not always the same, so you can't guarantee that one result will satisfy both timezones.
Consider using OffsetDateTime for your example
Printing the time now, and in "CET" is straightforward:
OffsetDateTime odt = OffsetDateTime.now();
System.out.println(odt); // 2018-10-26T11:25:49.215+01:00
System.out.println(odt.atZoneSameInstant(ZoneId.of("CET"))); // 2018-10-26T12:25:49.215+02:00[CET]
However, I don't believe there is a "CEST" in the ZoneID class.
So you could print the time of a particular country you know is in CEST and compare them.
For example, Algiers is currently in CET, but Amsterdam is in CEST:
System.out.println(odt.atZoneSameInstant(ZoneId.of("Europe/Amsterdam")));
System.out.println(odt.atZoneSameInstant(ZoneId.of("Africa/Algiers")));
Output:
2018-10-26T12:42:29.897+02:00[Europe/Amsterdam]
2018-10-26T11:42:29.897+01:00[Africa/Algiers]
The class you should be using is ZonedDateTime; as it has full time-zone support(including daylight savings).
Your code should be replaced with:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
ZonedDateTime utcTime = LocalDateTime.parse(ptu,formatter).atZone(ZoneId.of("UTC"));
ZonedDateTime yourTime = utcTime.withZoneSameLocal(ZoneId.of("Europe/Amsterdam"));
return yourTime.format(formatter);
Please refer below snippet :
ZonedDateTime dateTime =null;
Date finalDate = null;
DateTimeFormatter format =null;
String date = yourdate;
LocalDateTime lid = LocalDateTime.parse(date,
DateTimeFormatter.ofPattern(""yyyy-MM-dd"));
ZoneId id = ZoneId.of("GMT");//Add yours
ZonedDateTime gmtZonedDateTime = lid.atZone(id);
ZoneId zoneId = ZoneId.of("America/Los_Angeles"); //in case your add your
dateTime = gmtZonedDateTime.withZoneSameInstant(id);
format = DateTimeFormatter.ofPattern("yyyy-MM-dd");
SimpleDateFormat sfmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
finalDate = sfmt.parse(format.format(dateTime));
Hi i am currently work on creating Desktop application using Swing.I was able to convert IST to EST time using Date class in java but not able to convert EST to IST time and it gives same EST time as IST time. Please find the below code .
ChangetoEST function is giving correct EST time from IST time.
ChangetoIST function is not giving correct IST time from EST time and showing given EST time as IST time.
public String changetoEST(String date) throws ParseException
{
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
String dateInString = date;
Date d=formatter.parse(dateInString);
TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
formatter.setTimeZone(tzInAmerica);
String sDateInAmerica = formatter.format(d);
Date dateInAmerica = formatter.parse(sDateInAmerica);
String a=formatter.format(dateInAmerica);
return a;
}
public String changetoIST(String date) throws ParseException
{
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
String dateInString = date;
Date d=formatter.parse(dateInString);
TimeZone tzInIndian = TimeZone.getTimeZone("Asia/Calcutta");
formatter.setTimeZone(tzInIndian);
String sDateInAmerica = formatter.format(d);
Date dateInAmerica = formatter.parse(sDateInAmerica);
String a=formatter.format(dateInAmerica);
return a;
}
The parse calls are done without you explicitly setting a time zone, which means that parsing is done using your default time zone.
Set the source time zone before parsing, parse, set time zone to target time zone, and format result.
E.g.
public static String istToEst(String dateInput) throws ParseException {
return changeTimeZone(dateInput, TimeZone.getTimeZone("Asia/Calcutta"),
TimeZone.getTimeZone("America/New_York"));
}
public static String estToIst(String dateInput) throws ParseException {
return changeTimeZone(dateInput, TimeZone.getTimeZone("America/New_York"),
TimeZone.getTimeZone("Asia/Calcutta"));
}
private static String changeTimeZone(String dateInput, TimeZone sourceTimeZone,
TimeZone targetTimeZone) throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
formatter.setTimeZone(sourceTimeZone);
Date date = formatter.parse(dateInput);
formatter.setTimeZone(targetTimeZone);
return formatter.format(date);
}
Test
String dateInput = "08/22/2016 02:21 AM";
System.out.println(dateInput);
System.out.println(istToEst("08/22/2016 02:21 AM"));
System.out.println(estToIst("08/22/2016 02:21 AM"));
Output
08/22/2016 02:21 AM
08/21/2016 04:51 PM
08/22/2016 11:51 AM
Set formatter to the source timezone before parsing (this is the step you are missing), then set it to the destination timezone before formatting, otherwise it parses it using the local timezone, which is IST for you.
Also you should just be able to return sDateInAmerica directly, you don't need to re-parse then re-format it a second time.
java.time
You are using troublesome old legacy date-time classes, now supplanted by the java.time classes.
We parse the input string as a LocalDateTime as it lacks any info about offset-from-UTC or time zone (offset plus rules for anomalies such as DST).
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/yyyy hh:mm a" );
LocalDateTime ldt = LocalDateTime.parse( input , f );
Apply a time zone to get an actual moment on the timeline, a ZonedDateTime object.
ZoneId zNewYork = ZoneId.of( "America/New_York" );
ZonedDateTime zdtNewYork = ldt.atZone( zNewYork );
To see the same moment through the lens of another time zone, another wall-clock time, adjust into another ZoneId. Notice that we are not going through another LocalDateTime as the purpose of that class is to forget any information about offset or time zone. We want the opposite, to use the info about time zone to adjust wisely between zones. So while New York is behind UTC by four hours, India is ahead of UTC by five and a half hours. So we need a total of nine and a half hour adjustment, which may include a change in date.
ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = zdtNewYork.withZoneSameInstant( zKolkata ); // Same simultaneous moments on the timeline.
Generate String
You can generate a String in any format you desire to represent the date-time value.
String output = zdtKolkata.format( f );
Generally better to let java.time automatically localize for you.
Locale l = Locale.CANADA_FRENCH; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdtKolkata.format( f );
I have a date, for example Thu April 17 09:03:01 GMT 2014 in the timezone:
sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
and everytime a try to convert to UTC it returns Thu April 17 10:03:01 GMT 2014
This does not make sense because the corresponding UTC time is actually Thu April 17 08:03:01 GMT 2014 since that the in my timezone time is added 1hour due to daylight savings.
The code I use to convert is this:
//timeZone - id="Europe/London"
public static Date timeZoneConvertDate(Date date, TimeZone timeZone) {
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setTimeZone(timeZone);
sdf.applyPattern("dd-MM-yyyy HH:mm:ss");
String newDate = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
Date nd = sdf.parse(newDate);
return nd;
} catch (ParseException e) {
return null;
}
}
Could someone explain what I'm doing wrong?
tl;dr
A Date has no timezone associated with it, so you cannot create a method that adjusts the timezone of a date object. You need to work with Calendar objects if you want to retain TZ information or, preferably, take a look at Joda-Time.
Explanation of Your Output
A Date value has no timezone information; it's merely the number of milliseconds since the epoch. With that in mind, let's see what you're doing:
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setTimeZone(timeZone);
sdf.applyPattern("dd-MM-yyyy HH:mm:ss");
String newDate = sdf.format(date);
This part of your code creates a formatter that will print the date in the London timezone. So the result you'll get at the time of writing is approximately: 17-04-2014 11:38:15 (assuming you just created your date object).
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
Date nd = sdf.parse(newDate);
return nd;
} catch (ParseException e) {
return null;
}
Here you tell the date parser to read the date as though it were a UTC date. It uses that information to know how many milliseconds since the epoch have passed. The date object you get back still has no timezone associated with it.
UTC is an hour behind British Summer Time, so it will create a date object that appears an hour ahead when printed in the BST timezone. So when I print nd, I get: Thu Apr 17 12:38:15 BST 2014.
No Time Zone In java.util.Date
As the correct answer by Duncan said a java.util.Date has no time zone component. Confusingly its toString method applies the JVM's default time zone. To display in another time zone, use SimpleDateFormat to apply an adjustment.
Even better, avoid the notoriously troublesome java.util.Date, .Calendar, and SimpleDateFormat. Use either Joda-Time or the new java.time package in Java 8.
Joda-Time
In Joda-Time, a DateTime object truly does contain an assigned time zone. If you do not specify a time zone, the JVM's default time zone is assigned.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/London" );
DateTime dateTime = new DateTime( 2014, 4, 17, 9, 3, 1, timeZone );
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );
DateTime dateTimeIndia = dateTime.withZone( DateTimeZone.forID( "Asia/Kolkata" ) );
When run…
dateTime: 2014-04-17T09:03:01.000+01:00
dateTimeUtc: 2014-04-17T08:03:01.000Z
dateTimeIndia: 2014-04-17T13:33:01.000+05:30 (note the half-hour difference, +05:30)
You can easily convert back and forth to java.util.Date.
DateTime dateTime = new DateTime( myJUDate, timeZone );
…and…
Java.util.Date date = dateTime.toDate();
I am trying to convert a formatted date String to Date object. Date String is formatted to some other timezone.
When I do sdf.parse(String) it returns me my System date object.
Code is as below,
static Date convertGMTTime(String timeZone, long longDate){
Date convertedTime = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try{
Date date = new Date(longDate);
System.out.println("timezone: "+timeZone +", timestamp: "+date);
Locale locale = Locale.ENGLISH;
TimeZone destTimeZone = TimeZone.getTimeZone(timeZone);// TimeZone.getDefault();
System.out.println("Source timezone: "+destTimeZone);
/* DateFormat formatter = DateFormat.getDateTimeInstance(
DateFormat.DEFAULT,
DateFormat.DEFAULT,
locale);
formatter.setTimeZone(destTimeZone);*/
sdf.setTimeZone(destTimeZone);
String convertedDateStr = sdf.format(date);
System.out.println("convertedDateStr: "+convertedDateStr);
convertedTime = sdf.parse(convertedDateStr);
System.out.println("convertedTime: "+convertedTime + "sdf: "+sdf.getTimeZone());
}catch(Exception e){
e.printStackTrace();
}
return convertedTime;
}
I would appreciate if anyone could help and point out where I am going wrong.
Thanks in advance.
Output:
timezone: Atlantic/Cape_Verde, timestamp: Tue Jun 26 17:38:11 IST 2012
Source timezone: sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
convertedDateStr: 2012-06-26 11:08:11
convertedTime: Tue Jun 26 17:38:11 IST 2012
sdf:sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
Some more details to share, When I use another sdf object(without setting timezone for it), It do return me correct time and date but still timezone is picked from System clock
Code
static Date convertGMTTime(String timeZone, long longDate){
Date convertedTime = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdfParse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try{
Date date = new Date(longDate);
TimeZone destTimeZone = TimeZone.getTimeZone(timeZone);// TimeZone.getDefault();
System.out.println("Source timezone: "+destTimeZone);
sdf.setTimeZone(destTimeZone);
String convertedDateStr = sdf.format(date);
System.out.println("convertedDateStr: "+convertedDateStr );
convertedTime = sdfParse.parse(convertedDateStr,new ParsePosition(0));
System.out.println("convertedTime: "+convertedTime + "sdf: "+sdf.getTimeZone());
}catch(Exception e){
e.printStackTrace();
}
return convertedTime;
}
Output
Source timezone: sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
convertedDateStr: 2012-06-26 12:24:56
convertedTime: Tue Jun 26 12:24:56 IST 2012
sdf: sun.util.calendar.ZoneInfo[id="Atlantic/Cape_Verde",offset=-3600000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null]
I understand that when I do not assign timezone to sdf it takes System time zone, but why doesn't it show time in System time zone? I shows it in timezone as it was in String but Timezone is different.
Ans when I set timezone it returns date object as per my system time irrespective of the fact that sdf has some other time zone set.
Can anyone please explain the functional behavior for sdf.parse and sdf.format.
For me sdf.setTimeZone() does have its impact when we use format and it is nullified when we use sdf.parse(). I find it quite strange.
Appreciate help in this regard.
You already have a Date (or the number of milliseconds of the Date), so there is nothing to convert. A Date doesn't have any time zone. It's a universal instant in time. The time zone is relevant only when you display this date, because the date 65647678000 could be 12:38 in some time zone, but 10:38 in some other time zone. It's also relevant when you parse the String representation of a Date, because 10:38 is 65647678000 in some time zone, but is 65657678000 in some other.
While you don't display a Date object, or parse a String to a Date, you don't need to care about time zones. And to choose the time zone used when displaying/parsing it, set the time zone of the DateFormat, and then use DateFormat.format()/DateFormat.parse() to format/parse the date.
When you use Date.toString() to display a date, it will always use your current time zone.
I find it easier to understand what I mean by not thinking of a Date as a day, a month, a year, an hour, etc., but as a moment: "when Kennedy was shot". "When Kennedy was shot" is the same moment for everyone. But if you represent the moment "when Kennedy was shot" in Dallas time zone, it's not the same result as the result you get when you represent this same moment in Paris time zone.