Our timezones are stored in the database as follows (e.g. America/Los_Angeles). How do I get the equivalent GMT representation from the above (e.g. GMT -08:00)
Offset from GMT in hours:
import java.util.TimeZone
double offset = TimeZone.getTimeZone("America/Los_Angeles")
.getRawOffset()/(60*60*1000.0);
// returns 8.0
However, this returns the raw offset. The offset changes depending on the timezone and the date due to Daylight Time Savings. To get the offset for a particular date use:
import java.util.TimeZone
import java.util.Calendar
Calendar cal = Calendar.getInstance();
double offset = TimeZone.getTimeZone("America/Los_Angeles")
.getOffset(cal.getTimeInMillis())/(60*60*1000.0);
// returns -7.0 for 22/sep/2010
There's a huge difference between those two:
"America/Los_Angeles" lets you determine the local time given any UTC time
"GMT -08:00" only tells you the difference between local time and UTC at one instant. It doesn't tell you about when or whether DST is applied, or how much DST is applied
In other words, "GMT -08:00" is an offset, not a time zone. Now you can get the offset at any particular instant fairly easily - I would personally use Joda Time for that - and format it appropriately. But don't think that you've actually got a reasonable representation of a time zone.
Related
Searching up and down, right and left - don't find simple answer to this question:
I have java.util.Date instance, which get its value from mySQL.
Also I have time-zone code of the logged-in user.
I need to get the actual time at user time-zone.
For example:
My server-machine time-zone is GMT+2.
My date value in DB is: 2017-02-09 16:38:58.000
According to my server-machine-time-zone I get it into date instance as: 2017-02-09T16:38:58.000+0200
Now I need to know what to do if:
In case, for sample, my client-time-zone-code is GMT+4, I want to get:
2017-02-09 20:38:58.000
Pure date, that is right to my time zone and not contain "+4" or "GMT" indication.
In short words: convert my java.util.date to pure date that right to specific time-zone.
Sound very simple? after read very much documentaion, I already not sure that this is really simple.
Timestamp (with time zone)
As far as I have understood, the date-time in your database in UTC, but when you retrieve it, you (incorrectly) receive 2017-02-09T16:38:58.000+02:00.
First, if you can, change the datatype of your MySQL database column to timestamp (in some other databases it would be called timestamp with time zone). This will make sure that MySQL knows that the times are in UTC and should enable you to retrieve them as the right point in time rather than the right time of day in the wrong time zone. This in turn will give you the best starting point for converting to the client time zone.
java.time
Second, retrieve your value into an appropriate type from java.time, the modern Java date and time API. Avoid java.util.Date since it is poorly designed and cannot handle different time zones. For example, if your database datatype is datetime:
LocalDateTime dateTime = yourResultSet.getObject("your_col", LocalDateTime.class);
LocalDateTime is a date and time of day without time zone, so you cannot get the wrong time zone. Supply the offset that you know is right:
OffsetDateTime odt = dateTime.atOffset(ZoneOffset.UTC);
Convert to client time zone:
ZoneId clientTimeZone = ZoneId.of("Indian/Reunion");
ZonedDateTime clientDateTime = odt.atZoneSameInstant(clientTimeZone);
System.out.println(clientDateTime);
2017-02-09T20:38:58+04:00[Indian/Reunion]
Do yourself the favour of using a real time zone in the region/city format rather than an offset like +04:00. It’s easier to understand and more future-proof. Indian/Reunion is just an example, of course, use the correct one for your client.
The ZonedDateTime above has both offset and time zone in it. It’s recommended to keep it that way, and I don’t see it doing any harm. The client can always opt not to display it. If you still insist, convert to LocalDateTime again:
LocalDateTime clientDateTimeWithoutOffset = clientDateTime.toLocalDateTime();
System.out.println(clientDateTimeWithoutOffset);
2017-02-09T20:38:58
If the database datatype is timestamp:
OffsetDateTime odt = yourResultSet.getObject("your_col", OffsetDateTime.class);
This saves the first step above. The remainder is the same.
Link
Oracle tutorial: Date Time explaining how to use java.time.
java.util.Date does not store any time zone. It just stores the number of milliseconds since the 'epoch', which is 1 January 1970, 00:00:00 UTC.
Thus, all you have to do is to know the time zone of your server machine, find the period between this time zone and the time zone you want to convert it to and add or subtract the period.
UPDATE:
int clientGMT = 4; //GMT you want to convert to
int serverGMT = 2; //server's GMT
int delta = clientGMT - serverGMT; //delta between the dates
//assume this is the date in GMT + 2 received from the server
Date d1 = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss").parse("12.03.2019 13:00:00");
//... and you want to convert it to GMT + 4 (client side's time zone)
Date resultDate = new Date(d1.getTime() + delta * 3600000);
P.S. Yes, you have to manipulate time zones manually, as I said above, java.util.Date does not store this information (each date is assumed to be in UTC).
I'm not familiar with Joda DateTimeFormatter, so I'm wondering if there is no time zone specified for DateTimeFormatter, what will be the default time zone? For example I have:
DateTimeFormatter stdFormatter = DateTimeFormat.forPattern("MM/dd/yyyy");
DateTime today = stdFormatter.parseDateTime("07/20/2017");
In this case, what would be the time zone of today? Is it gonna be 2017-07-20 00:00:00 UTC by default? Thank you!
Referring to the DateTime documentation here, the DateTime internally stores the value as milliseconds past 1970-01-01T00:00:00Z, where Z is the UTC zone.
The way it is output depends on how you decide to format it (i.e. if you want to print the DateTime in a different time zone, you can use the Joda libraries to do so).
In this case, DateTimeFormat.forPattern uses the JVM default locale, which is determined by Locale.getDefault(), whatever that may be for you. So, your DateTime will contain the time at UTC for '07/20/2017 00:00:00 {YOUR TIME ZONE}'.
Say your time zone is PDT (i.e. UTC-7). Then "07/20/2017 00:00:00 PDT" == "07/20/2017 07:00:00 UTC". Your DateTime object will store that UTC time.
DateTime dt = new DateTime("2014-09-15T21:20:14");
System.out.println(dt);
System.out.println(dt.plusMillis(581042272).toDateTime().toLocalDateTime().toDateTime(DateTimeZone.forID("GMT")));
the time in dt is in UTC, I want to set the time in dt plus milliseconds to GMT? However, the time is still printed as UTC (1 hour behind GMT). How can I set it so it's one hour in front?
2014-09-15T21:20:14.000+01:00
2014-09-22T14:44:16.272Z
I know the time is exactly one hour behind because I made this request at 15:44:16 GMT
Your DateTime is actually not in UTC - it's in the system default time zone. To fix it, you just need to tell it that the value you're passing in is in UTC:
DateTime dt = new DateTime("2014-09-15T21:20:14", DateTimeZone.UTC);
System.out.println(dt);
DateTime other = dt.plusMillis(581042272);
System.out.println(other);
Output:
2014-09-15T21:20:14.000Z
2014-09-22T14:44:16.272Z
Also note that you can't have made the request at 15:44:16 GMT, as that hasn't occurred yet. At the time I'm writing this, it's 16:05 British Summer Time, therefore 15:05 GMT. It's important to understand that the time zone in the UK isn't "GMT" - that's just the part of the time zone when we're not observing daylight savings.
If you want to convert to the UK time zone, you want:
DateTime other = dt.plusMillis(581042272)
.withZone(DateTimeZone.forID("Europe/London"));
For those that have trouble with converting datetime from a server to local datetime:
1.Make sure the server gives you a UTC time, meaning, the format should contain a timezone.
2.Convert with pattern, if the api does not give you an timezone, then you might get an exception because of the last 'Z'.
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
DateTime dt = formatter.parseDateTime(currentPost.postDate);
3.to check the time offset (optional)
DateTimeZone ActualZone = dt.getZone();
4.Convert to local time
TimeZone tz2 = TimeZone.getDefault();
DateTime localdt = new DateTime(dt, DateTimeZone.forID(tz2.getID()));
(if you control the API yourself, and it happens to be an asp.net api, check this, to set the Kind of the datetime, even though you might have saved it as UTC time in the database, you will send the datetime with the default server timezone)
val marketCentreTime = timeInAnotherTimezone.withZone(DateTimeZone.forID("yourCountryName/andyourCityName"));
I have the following code.
//this line returns - UTC
TimeZone timeZone = TimeZone.getDefault();
//date1 - todays date in UTC format
boolean dstInit = timeZone.inDaylightTime(date1);
//date2 - todays date in UTC format
boolean dstNext = timeZone.inDaylightTime(date2);
But due to some reason both dstInit and dstNext returning false (instead of TRUE).
date1 and date2 is June 20, 2014 in UST formnat which falls in DST time between march and october. Can anyone please help me in fixing this issue?
UTC is not a format. It's a system of timekeeping.
TAI - Measured from precise atomic clocks
UT1 - Measured from the imprecise rotation of the Earth
UTC - Calculated by adding leap seconds to TAI to align it to within 0.9 seconds of UT1.
UTC is the common standard we use in computing. A time in UTC can be expressed in a wide variety of formats, however it is always the same time for everyone. It is not affected by time zones, and it never changes for daylight saving time.
//date1 - todays date in UTC format
boolean dstInit = timeZone.inDaylightTime(date1);
If date1 is a java Date object, then the comment is wrong. A Java Date is a dumb wrapper over a long , it only represents an instant point in the "physical" time, it does not store a Timezone (nor civil date fields), and it has no "format".
Hence, the above line is simply telling if that instant, in that timezone (UTC) corresponds to daylightTime. Of course, it will return false always, because the UTC (pseudo) timezone does not have DST.
[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