Converting from EST to EDT in Java [duplicate] - java

Can anybody tell about three things:
How to retrieve TimeZone from java.util.Date instance?
How to know whether Daylight savings is applicable?I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000)
How to convert EST time to EDT or vice versa?

How to retrieve TimeZone from java.util.Date instance?
There's no such thing. A Date just represents a number of milliseconds since the Unix epoch, which was midnight on January 1st 1970 UTC. It's not associated with a particular calendar system or time zone. To put it another way, if a friend and I are on the phone together (with a zero latency ;) and I click my fingers, we would both agree on the Date at which that click too place - even if I'm using the Gregorian calendar and he's using the Julian calendar, and even if I'm in London and he's in New York. It's the same instant in time.
How to know whether Daylight savings is applicable?, I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000)
Ideally, use Joda Time instead of java.util.Date/Calendar/TimeZone, but within TimeZone you can use TimeZone.getOffset(long) to find the offset from UTC, or TimeZone.inDaylightTime(Date) to just give you a yes/no answer.
How to convert EST time to EDT or vice versa?
Usually that's an invalid question - because at any one instance in time, either EST or EDT applies. You normally convert from one time zone to another, and "EDT" and "EST" aren't different time zones - they're different offsets within the same time zone. The fact that you're asking for this suggests that you may be modelling your data incorrectly to start with (which is unfortunately easy to do with date/time values). Please give us more information and we may be able to help you more.

Date stores the time in milliseconds since the 1970 epoch, so doesn't contain timezone information. Your JVM has a locale set which defines how this date is then displayed.
If you want to find out what TimeZone your JVM has set, call 'TimeZone.getDefault()'
Once you have a TimeZone object, you can call a number of functions to determine if for that timezone, daylight savings applies to a give date:
inDaylightTime(Date)
To (crudely) determine the difference between two TimeZones:
long edtOffset = TimeZone.getTimeZone("EDT").getOffset(date.getTime());
long estOffset = TimeZone.getTimeZone("EST").getOffset(date.getTime());
long diff = estOffset - edtOffset;
Although I'm not sure how valid this is as EST and EDT are mutually exclusive, and whether the above code will even give you the result you're interested in (I've not tested it)

How to retrieve TimeZone from java.util.Date instance?
You can view the Time Zone of an instantiated Date object by viewing it in toString() format. Such as "Wed May 01 12:00:00 EDT 2013".
How to know whether Daylight savings is applicable?, I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000) 3. How to convert EST time to EDT or vice versa? This is critical question I have
The Date object will account for the EDT/EST automatically. For instance, if you have an instantiated Date object for November 28, then the toString() will include EST rather than EDT.
The problem I originally ran into was that I was trying to use EST for a calendar date where Daylight Savings Time was active, and the Date object was automatically correcting my mistake by adding an hour to my time and displaying EDT.

I ran into a similar problem. The following solution is in Matlab but calling Java, and my changes are just comments because I'm working with Matlab datenum values. You wouldn't really be able to convert timezone aware values, since they are the same timezone, but this may help with raw values that are not timezone aware.
%c1 GregorianCalendar of now
%c2 GregorianCalendar of date in question
tz1 = c1.getTimeZone; %Note t2 would be the same
in1 = tz1.inDaylightTime(c1.getTime);
in2 = tz1.inDaylightTime(c2.getTime);
if (in1 == in2)
%do nothing
elseif in1
%c1 EDT, c2 is EST
%Subtract 1 hour to c2
else
%c1 EST, c2 EDT
%Add 1 hour to c2
end

Related

How to handle CST to CDT or vice versa using XMLGregorianCalendar

I had the below issue During daylight change CST-CDT reset.
Am getting the Input from Was8.5 server 2018-03-11-05.00 (UTC-5) as expected, but when it comes to WAS7 server, the below method returns Sun Mar 10 00.00.00 CST 2018 instead of Sun Mar 11 00.00.00 CDT 2018
/*
* Converts XMLGregorianCalendar to java.util.Date
*/
public static Date toDate(XMLGregorianCalendar calendar){
if(calendar == null) {
return null;
}
return calendar.toGregorianCalendar().getTime();
}
I know the server date/timezone reset didn’t take place properly, but in case if I want to get right Time when CST to CDT change or vise versa. How can I rewrite the code to convert XMLGregorianCalendar to java.util.Date in Java?
Something like,
If incoming request was CST(UTC-6), the toDate(XMLGregorianCalendar calendar) returns CDT (UTC-5). then I want toDate() should return CST (UTC-6).
the same way,
If incoming request was CDT(UTC-5), the toDate(XMLGregorianCalendar calendar) returns CST(UTC-6). then i want toDate() should return CDT(UTC-5).
java.util.Date doesn't have a timezone. It just have a long value that represents the number of milliseconds since unix epoch.
What you see (Sun Mar 10 00.00.00 CST 2018) is the result of toString() method, and it uses the JVM default timezone to convert the long value to a date and time in that timezone. See this article for more details:
https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util-date/
Anyway, one way to really know what's happening is to check this long value:
long millis = calendar.toGregorianCalendar().getTimeInMillis();
And then you can print this value in UTC:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss XXX");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.format(new Date(millis)));
Or, if you use Java 8:
System.out.println(Instant.ofEpochMilli(millis));
This will tell you the UTC instant that the Date corresponds to, so you can debug your code a little better than relying on Date::toString() method, which is confusing and misleading.
Regarding your main issue, I've tried to reproduce (I'm using Java 8 because it's easier to manipulate than using Date). First I created a date/time corresponding to 2018-03-11 in UTC-05:00, and I assumed the time to be midnight:
// March 11th 2018, midnight, UTC-05:00
OffsetDateTime odt = OffsetDateTime.parse("2018-03-11T00:00-05:00");
Then I converted this to America/Chicago timezone, which is a zone that uses CST/CDT:
// get the same instant in Central Time
ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("America/Chicago"));
Then I printed this:
// print the date/time with timezone abbreviation
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm xxx z", Locale.US);
System.out.println(zdt.format(fmt)); // 2018-03-10 23:00 -06:00 CST
Note that the result is 2018-03-10 23:00 -06:00 CST: March 10th in UTC-06:00.
That's because in 2018, Daylight Saving Time starts only at 2 AM of March 11th. At midnight, DST has not started yet, so the offset is still UTC-06:00.
Anyway, your conversion code is correct, because Date just represents a point in time (a count of elapsed time since epoch) and doesn't have timezone attached to it. Perhaps the problem lies somewhere, and checking the millis value might help you to understand what's going on (my guess is that XmlGregorianCalendar sets the time to midnight when it's not present, which would explain the result of Sun Mar 10 00.00.00 CST 2018).
If that helps, the exact UTC instant where DST transition occurs (March 11th 2018 at 2 AM in UTC-06:00) corresponds to the millis value 1520755200000. If your dates in March 2018 have a value lower than that, it means they're before DST starts, and they'll be in CST.
My first suggestion is that you don’t need what you are asking for. As I see it, you’ve got a date and a UTC offset, and I don’t really see that the offset adds any useful information. Just take the date. I believe what has happened was that a point in time after the transition to summer time on March 11 was stripped of the time-of-day, but the UTC offset was kept for whatever reason or maybe for no reason at all. When giving the time at start of day (00:00), the offset disagrees with your time zone of America/Chicago (or Central Time Zone, but the ID in region/city format is unambiguous and recommended).
And don’t use java.util.Date for your date. That class is long outdated. Today we have so much better in java.time, the modern Java date and time API. Furthermore its LocalDate class is better suited for a date without time-of-day because this is exactly what it is, while a Date is really a point a in time, that is, a whole different story. Depending on taste conversion from XMLGregorianCalendar can happen in two ways.
The direct way
return LocalDate.of(calendar.getYear(), calendar.getMonth(), calendar.getDay());
With your XMLGregorianCalendar of 2018-03-11-05:00 the result is a LocalDate of 2018-03-11.
The indirect way via GregorianCalendar and ZonedDateTime:
return calendar.toGregorianCalendar().toZonedDateTime().toLocalDate();
The result is the same. The advantage of the latter is you don’t need to concern yourself with the individual fields of year, month and day-of-month. Among other things this means you don’t risk putting them in the wrong order.
If you do insist on keeping the time zone or UTC offset, at least take the offset. Sun Mar 11 00.00.00 CDT 2018 doesn’t make sense because March 11 at 00:00 hours DST was not yet in effect (it began at 02:00). Such a non-existing time will just confuse everyone. Convert your calendar object to OffsetDateTime:
return calendar.toGregorianCalendar().toZonedDateTime().toOffsetDateTime();
Result: 2018-03-11T00:00-05:00. This point in time exists.:-)
Since your calendar comes from a foreign system, you will probably want to validate it since any field may be undefined and return DatatypeConstants.FIELD_UNDEFINED. When using LocalDate.of(), you may decide that its argument validation is enough since it will object to DatatypeConstants.FIELD_UNDEFINED being passed as an argument. toGregorianCalendar() on the other hand will tacitly use default values, so when using it I would consider validation indispensable.
What went wrong in your code?
I ran your code, and similarly to iolus (see the other answer) I got Sat Mar 10 23:00:00 CST 2018. This the correct point in time. As iolus also explained, this is Date.toString rendering the point in time this way. The Date object itself doesn’t have a time zone or UTC offset in it. So I should say that your code was correct. It was just you getting confused by the toString method. Many have been before you, and the good solution is to avoid the Date class completely. Also I would think that your observations have nothing to do with any difference between WAS 7 and WAS 8.5.

How to set a date in certain timezone? [duplicate]

This question already has answers here:
How to set time zone of a java.util.Date?
(12 answers)
Closed 5 years ago.
I am using timer to perform certain tasks in certain period. This method requires Date type if you want to make the task start from that date and repeat in every period.
I have been trying to find solution for this for hours but couldn't come up with anything. I create calendar and set a timezone for it. Then when I get date from that calendar this date contains my LOCAL TIME. I tried getting string from Date using SimpleDataFormat and it worked because you set timezone for SimpleDataFormat separately. Then even tried parsing that string into the date but it still didn't work. I'm kinda hopeless at this moment. What's the point of setting timezone for calendar if I'm not able to use it. I could still do something if it wasn't getting my local time but instead it was getting UTC. But that's not the case either. I don't want to make this application run based on the computer's local time. That's absurd it should be able to get local time and turn it into the time zone I want and use it like that.
Code:
TimeZone eu = TimeZone.getTimeZone("GMT+1");
TimeZone america = TimeZone.getTimeZone("EST");
TimeZone asia = TimeZone.getTimeZone("GMT+7");
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
df.setTimeZone(eu);
Calendar euCal = Calendar.getInstance(eu);
Date dateEu = euCal.getTime();
System.out.println(dateEu); //Prints local time date
euCal.setTimeZone(eu);
System.out.println(dateEu); //Still prints local time date
String formattedDateEu = df.format(dateEu);
System.out.println(formattedDateEu); //This one works fine but it is string
try {
dateEu = df.parse(formattedDateEu);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(dateEu); //Fun part. Although I don't get exception dateEu is still not in the time zone I want.
Sample Output:
Mon Nov 27 14:37:21 MSK 2017
Mon Nov 27 14:37:21 MSK 2017
27/11/2017 12:37:21
Mon Nov 27 14:37:21 MSK 2017
java.util.Date objects don't contain time zone information. They represent an instant in the time continuum that is the same instant for everyone regardless of whether they so happen to be in Paris or New York at the moment.
However, when you try to print a Date object with System.out.println() it needs to try and describe itself. So it will need to describe the date and time it represents, but to do that it first needs to choose a time zone to represent this date and time in, since it doesn't have one. For convenience it chooses the user's system time zone.
You're not going to use your Date by calling System.out.println() with it, so you shouldn't care what System.out.println() does with it.
I wish I could tell you to stay away from the long outdated Date class. Today we have so much better in java.time, the modern Java date and time API. However, you are correct that java.util.Timer does need a Date for scheduling a task at a specific date and time. Still, since the modern API is so much nicer to work with, I recommend you use it for initializing your Date:
ZoneOffset eu = ZoneOffset.ofHours(1);
ZoneOffset america = ZoneOffset.ofHours(-5);
ZoneOffset asia = ZoneOffset.ofHours(7);
OffsetDateTime euTime = OffsetDateTime.now(eu);
System.out.println(euTime);
Date dateEu = Date.from(euTime.toInstant());
// schedule to start at the specified date-time and repeat weekly
myJavaUtilTimer.scheduleAtFixedRate(myTask, dateEu, TimeUnit.DAYS.toMillis(7));
I appears to me you aren’t really using time zones, just offsets from GMT (or UTC). So I put in some ZoneOffsets in the code. The result of printing euTime just now was
2017-11-27T15:56:03.213+01:00
You can see that the offset is +01:00 as expected. Then, as kumesana already said in the other answer, don’t print the resulting Date, just trust that it’s OK.
If you do prefer real time zones, use for example:
ZoneId eu = ZoneId.of("Europe/Brussels");
ZoneId america = ZoneId.of("America/Jamaica");
ZoneId asia = ZoneId.of("Asia/Krasnoyarsk");
The rest of the code is the same. That’s true: OffsetDateTime.now() accepts either a ZoneOffset or a ZoneId, so you can even mix both types. Of the above time zones, Europe/Brussels uses summer time (DST), so you will get an offset of +02:00 during 7 months of the year.
Avoid the three letter time zone abbreviations like EST. They are often ambiguous. Do prefer to specify your time zones in the region/city format as I do in my code.
EDIT: Here’s an example run from my computer:
2017-11-28T19:04:22.917+01:00
myTask running # 2017-11-28T19:04:23.156+01:00[Europe/Oslo]
As you can see, myTask ran 239 milliseconds after the specified firstTime for the scheduled task. Such latency should be expected. In a second run, the difference was down to 130 ms.

DateTime getDayOfYear() Returning 366 for 12-31-2013 instead of 365

Does anyone know why this method is behaving this way? 2013 is not a leap year, so I would expect that if I have a DateTime object like:
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dt = formatter.parseDateTime("2013-12-31 23:59:52");
That
dt.getDayOfYear()
would give me 365 but it's giving me 366. Can anyone see what the problem is?
I am also getting 366 if I do
dt.toString("DDD");
I would appreciate any input anyone might have.
Let me try an answer based on what I read from the docs and the code.
I assume your time stamp is indeed what you think it is, namely that last minute of 2013 UTC.
You create a DateTime object with the stamp in the default timezone. So if your local time zone is +01:00, this is 2013-14-01 00:59 +01:00.
Now you use withZoneRetainFields(UTC). From the docs I understand that this changes the milliseconds such that they actually reflect 2014-01-01 00:59 UTC, Basically this requires to add 3600*1000 millis to the time stamp, while changing the time zone entry in the object to UTC.
When you then ask for the day of the year, what actually happens internally is
.dayOfYear().get(getMillis())
My hunch is that dayOfYear is still based on 2013 and from this baseline you get day 366.
(I am not totally convinced myself of this answer I must admit and I wonder if there might be simply a bug lurking in Joda.)
Anyway: if you have UTC timestamps, I might suggest to just use new DateTime(stamp, UTC) where UTC a DateTimeZone object. Thereby you avoid the mind-bending double zone shifting.
EDIT: Further, if your stamp from the DB is genuinely UTC, by usingwithZoneRetainFields you change that stamp to denote another point in time, which has a good chance of being the wrong way to do whatever you are actually trying to do. In the confusing area of date/time handling, the time stamp in millis is the one easy to understand item. If it is not just for display purposes, I would never touch it.

Converting EST to EDT or vice versa in Java

Can anybody tell about three things:
How to retrieve TimeZone from java.util.Date instance?
How to know whether Daylight savings is applicable?I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000)
How to convert EST time to EDT or vice versa?
How to retrieve TimeZone from java.util.Date instance?
There's no such thing. A Date just represents a number of milliseconds since the Unix epoch, which was midnight on January 1st 1970 UTC. It's not associated with a particular calendar system or time zone. To put it another way, if a friend and I are on the phone together (with a zero latency ;) and I click my fingers, we would both agree on the Date at which that click too place - even if I'm using the Gregorian calendar and he's using the Julian calendar, and even if I'm in London and he's in New York. It's the same instant in time.
How to know whether Daylight savings is applicable?, I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000)
Ideally, use Joda Time instead of java.util.Date/Calendar/TimeZone, but within TimeZone you can use TimeZone.getOffset(long) to find the offset from UTC, or TimeZone.inDaylightTime(Date) to just give you a yes/no answer.
How to convert EST time to EDT or vice versa?
Usually that's an invalid question - because at any one instance in time, either EST or EDT applies. You normally convert from one time zone to another, and "EDT" and "EST" aren't different time zones - they're different offsets within the same time zone. The fact that you're asking for this suggests that you may be modelling your data incorrectly to start with (which is unfortunately easy to do with date/time values). Please give us more information and we may be able to help you more.
Date stores the time in milliseconds since the 1970 epoch, so doesn't contain timezone information. Your JVM has a locale set which defines how this date is then displayed.
If you want to find out what TimeZone your JVM has set, call 'TimeZone.getDefault()'
Once you have a TimeZone object, you can call a number of functions to determine if for that timezone, daylight savings applies to a give date:
inDaylightTime(Date)
To (crudely) determine the difference between two TimeZones:
long edtOffset = TimeZone.getTimeZone("EDT").getOffset(date.getTime());
long estOffset = TimeZone.getTimeZone("EST").getOffset(date.getTime());
long diff = estOffset - edtOffset;
Although I'm not sure how valid this is as EST and EDT are mutually exclusive, and whether the above code will even give you the result you're interested in (I've not tested it)
How to retrieve TimeZone from java.util.Date instance?
You can view the Time Zone of an instantiated Date object by viewing it in toString() format. Such as "Wed May 01 12:00:00 EDT 2013".
How to know whether Daylight savings is applicable?, I suppose I can know it by doing timeZone.getDSTSavings, but problem I am facing is that even if I make my system's date as Feb 1 2012, still I am getting the value as positive (I guess 3600000) 3. How to convert EST time to EDT or vice versa? This is critical question I have
The Date object will account for the EDT/EST automatically. For instance, if you have an instantiated Date object for November 28, then the toString() will include EST rather than EDT.
The problem I originally ran into was that I was trying to use EST for a calendar date where Daylight Savings Time was active, and the Date object was automatically correcting my mistake by adding an hour to my time and displaying EDT.
I ran into a similar problem. The following solution is in Matlab but calling Java, and my changes are just comments because I'm working with Matlab datenum values. You wouldn't really be able to convert timezone aware values, since they are the same timezone, but this may help with raw values that are not timezone aware.
%c1 GregorianCalendar of now
%c2 GregorianCalendar of date in question
tz1 = c1.getTimeZone; %Note t2 would be the same
in1 = tz1.inDaylightTime(c1.getTime);
in2 = tz1.inDaylightTime(c2.getTime);
if (in1 == in2)
%do nothing
elseif in1
%c1 EDT, c2 is EST
%Subtract 1 hour to c2
else
%c1 EST, c2 EDT
%Add 1 hour to c2
end

Time Zones in Java / GWT (Client-side)

[Client-side GWT class]
I have a Date Object...
Date dataObject = DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")
.parse("2009-10-12T00:00:00.000);
This works fine. However when I do a:
dateObject.getTime();
It returns a UNIX Time milliseconds using a GMT with daylight savings, therefore making it a UNIX Time I cannot use. I need it in UTC. How do I do this?
Currently I'm parsing a date and it is giving me back:
'Thu Apr 16 08:46:20 GMT+100 2009' # '1239867980191'
However the date I'm passing in is 1 hour less than this time (7:46 and not 8:46!).
How do I pass in the fact it's UTC? Or if it can't use UTC (which would be ridiculous), how do I use GMT without the daylight savings?
Your last edit makes things clearer.
Basically, you are confused, and you already get what you want.
1239867980191 milliseconds since the Epoch translates to Thursday, April 16th, 2009, at 7:46:20.191 in the GMT time zone. The very same instant translates to the same day, but 8:46:20.191 in the GMT+01 time zone. If your input string specified "7:46:20.191" and you indeed got 1239867980191 from Date.getTime() then congratulations, the parsing code understood your "7:46:20.191" as to be interpreted in the GMT time zone, and did it properly.
If afterwards you get "8:46:20" when printing, this is only because you use the GMT+01 time zone for displaying that instant. Note that the string contains GMT+100 precisely to notify you that it uses that time zone for display purposes. The instant which the Date instance represents is nonetheless exactly the instant you wish it to contain. Remember that a Date instance represents an instant in time, for which no notion of time zone applies: time zones are used to convert instants into calendar elements (days, hours...) and back.
To convert a Date to a displayable string, use DateTimeFormat.format(Date, TimeZone) which lets you specify which time zone you want to use for that string.
Since the Calendar class is not supported in GWT, maybe something hackish like this will work:
final String timezone = "GMT-07:00";
DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ssZZZZ");
long unix = dtf.parse("2009-10-12T00:00:00" + timezone).getTime();
This way you can provide the correct timezone info - though, that should be the default behaviour.
It is the other way round. A Date instance holds the time in milliseconds since the Epoch, using the UTC time scale (i.e. leap seconds are ignored). This is what Date.getTime() returns and that's what you want.
The culprit here is the parser, which interprets the date you give as a string in your local time zone. If you want DateTimeFormat to interpret the string as a date-and-time given in the UTC time zone, append an explicit time zone to the parsed string:
DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ssZZZZ")
.parse("2009-10-12T00:00:00.000" + " GMT");
(The above assumes that I understood GWT documentation properly; I have not tried.)
Just to be clear in my notations: for all practical purposes, there is no difference between "GMT" and "UTC", and there is no daylight saving in the GMT time zone. Other time zones are often defined as "GMT plus or minus some offset" and the offset may change between summer and winter. For instance, the time zone in New York is somewhat equivalent to "GMT-04" in summer and "GMT-05" in winter.
I keep seeing formats with ZZZZ being suggested... but why?
"yyyy-MM-dd'T'HH:mm:ss.SSSZ" would match
"2009-10-12T00:00:00.000-0000"
The last part being the offset from UTC; California (to use someone else's example time) would be -0800, -0700 in summer.
As a side note, GMT is also always -0000. That's why Britain's summer time zone is BST (British Summer Time, +0100).
Try the Calendar object.
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Date dataObject = DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")
.parse("2009-10-12T00:00:00.000);
cal.setTime(dataObject);
cal.getTimeInMillis();
According to the API, getTimeInMillis() returns "the current time as UTC milliseconds from the epoch."
EDIT: as _bravado pointed out, the Calendar API is currently not available for GWT (Issue 603). While this would get the appropriate time in a Java application, it isn't going to work here. There is information in the group about using GMT.
EDIT: Missing a closing bracket on the the Calendar.getInstance() call

Categories