I have one simple question. How to achieve this format of date 1438117140000+0300. First part 1438117140000 its the time in millisec , that i convert with no problem, second part with timezone info is my headache , how to get it ??
You can use String.format for this purpose:
Date now = new Date();
System.out.println(String.format("%tQ%tz", now, now));
Executing the code just printed out this:
1438635740416+0300
The conversions for date/time are specified in the documentation. Here, I've used the following two conversion characters:
'Q': Milliseconds since the beginning of the epoch starting at 1
January 1970 00:00:00 UTC, i.e. Long.MIN_VALUE to Long.MAX_VALUE.
'z': RFC 822 style numeric time zone offset from GMT, e.g. -0800. This
value will be adjusted as necessary for Daylight Saving Time. For
long, Long, and Date the time zone used is the default time zone for
this instance of the Java virtual machine.
It looks like +0300 means +3 hours from GMT. so convert 0300 (3 hours) to milliseconds and add to 1438117140000. then convert to a date time as you are already
Split the value you have to '+' then add 3 hours as miliseconds to the first value of the array that split method returned.
Related
Based on Epoch seconds, I convert it to the start of hour and end of hour.
long epochSeconds = 1589374800L;
Instant instant = Instant.ofEpochSecond(epochSeconds);
Calendar now = Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("Asia/Kolkata")));
now.setTimeInMillis(instant.toEpochMilli());
System.out.println(now.getTime()); // Correct --> Wed May 13 06:00:00 PDT 2020
Calendar endOfHour = (Calendar)now.clone();
endOfHour.set(Calendar.MINUTE, 59);
endOfHour.set(Calendar.SECOND, 59);
endOfHour.set(Calendar.MILLISECOND, 999);
System.out.println(endOfHour.getTime()); // Wrong ---> Wed May 13 06:29:59 PDT 2020
The start of hour seems correct, but the end of hour is not giving it right, instead of upto 59 minute, 59 second, 999 millisecond it is giving only half hour difference.
You are mixing java.time and java.util.Calendar types. Don't do that. For one thing, you're losing the TimeZone you specified when you clone. Basically, Calendar is a mess. But you don't need it here, something like
long epochSeconds = 1589374800L;
LocalDateTime date = Instant.ofEpochSecond(epochSeconds) //
.atZone(ZoneId.of("Asia/Kolkata")) //
.toLocalDateTime();
System.out.println(date);
LocalDateTime endOfHour = date.withMinute(59) //
.withSecond(59) //
.with(ChronoField.MILLI_OF_SECOND, 999);
System.out.println(endOfHour);
Should meet your needs. Here that outputs
2020-05-13T18:30
2020-05-13T18:59:59.999
Two points (and one more at the end):
Just repeating what has already been said: don’t mix old and modern date-time classes. Use the modern ones exclusively. Forget about the old ones. They were always poorly designed anyway.
Your observed result is correct and as should be expected.
You are using Asia/Kolkata time zone for your (outmoded) Calendar object. Asia/Kolkata time zone is special in that it is not offset a whole number of hours from UTC as most time zones are, but +05:30, five and a half hours. Let’s look at your times in this time zone first. Your epoch second value (AKA Unix timestamp) is equal to 2020-05-13T18:30:00+05:30 in Asia/Kolkata. The end of that hour in Asia/Kolkata is 2020-05-13T18:59:59.999. This is the result that you get.
It seems that you are running your program on a JVM in a different time zone (perhaps America/Vancouver or America/Los_Angeles). This time zone is offset a whole number of hours from UTC, so 18:59:59.999 in India equals 06:29:59 PDT (your time zone).
Half-open:
I promised you a third point. Represent the end of the hour as the whole hour, here 19:00 rather than 18:59:59 and some number of 9s. The philosophical argument: The hour doesn’t end one millisecond before the next hour begins, so this is incorrect. The practical argument: It frees you from deciding how many 9s you need. java.time has nanosecond precision, so is able to represent nearly a million points in time between your end of the hour and the beginning of the next hour. You risk hitting such a point and assigning it to the wrong hour. In comparisons just make sure that you are checking whether a point in time is strictly before the whole hour where the hour ends.
If you do need Calendar objects for a legacy API:
ZoneId zone = ZoneId.of("Asia/Kolkata");
long epochSeconds = 1589374800L;
ZonedDateTime now = Instant.ofEpochSecond(epochSeconds).atZone(zone);
Calendar nowAsOldfashionedCalendar = GregorianCalendar.from(now);
ZonedDateTime endOfHour
= now.plusHours(1).truncatedTo(ChronoUnit.HOURS).minusNanos(1);
Calendar endOfHourAsOldfashionedCalendar = GregorianCalendar.from(endOfHour);
I included .minusNanos(1) to get the last nanosecond of the previous hour, but as I said, you should prefer to omit it if you can. The conversion to GregorianCalendar will truncate to milliseconds and give you the same result as in your code in the question.
I am working with an API that provides me with a ModifyDate field that is being given in CST (-06:00), but when passing the string in to Joda time and setting the time zone to America/Phoenix, Joda time thinks that the date/time I gave it is in UTC time zone because there is no offset information being given by the API (the time being returned is in CST, confirmed with the developers).
Side note: I am in Arizona where we do not recognize daylight savings time, so I can't just apply a static offset of -1 hour.
Here's an example of what I'm dealing with:
Field returned by the API:
"modifyDate": "2020-02-11T12:23:39.817Z"
Trying to format the date with Joda time:
DateTime time1 = new DateTime("2020-02-11T12:23:39.817Z", DateTimeZone.forID("CST6CDT"));
System.out.println(time1);
DateTime time2 = new DateTime(time1, DateTimeZone.forID("America/Phoenix"));
System.out.println(time2);
System.out.println("----------------------------");
DateTime time3 = DateTime.parse("2020-02-11T12:23:39.817Z");
System.out.println(time3);
System.out.println(time3.toInstant());
System.out.println(time3.withZone(DateTimeZone.forID("America/Phoenix")));
System.out.println(time3.toDateTimeISO());
System.out.println(time3.toDate());
System.out.println("--------------------------------");
Output:
2020-02-11T06:23:39.817-06:00
2020-02-11T05:23:39.817-07:00
----------------------------
2020-02-11T12:23:39.817Z
2020-02-11T12:23:39.817Z
2020-02-11T05:23:39.817-07:00
2020-02-11T12:23:39.817Z
Tue Feb 11 05:23:39 MST 2020
--------------------------------
As you can see in the first two outputs, by trying to apply the time zone for CST, the time provided is offset by -6 (to be expected if the time provided was in UTC). By setting the time zone to America/Phoenix, the offset is -7 (also to be expected). However, as I mentioned, the time that I am passing into DateTime is not UTC, it is CST.
How can I tell DateTime (or even some other library, for that matter) that the time being provided is in CST? Again, keeping in mind that when daylight savings time changes, the offset needs to be managed properly.
In this case, the time being provided by the API was incorrectly being provided as UTC, even though the time is CST, as pointed out by OleV.V. The cleanest solution to this problem was to use DateTime.withZoneRetainFields(), as mentioned by shmosel.
For whatever reason, however, if I created the DateTime object by using the constructor, I couldn't adjust the time zone with withZoneRetainFields(), instead, I had to use DateTime.parse().
I adjusted for the time zone being off by using the following logic:
DateTime time4 = DateTime.parse("2020-02-11T12:23:39.817Z").withZoneRetainFields(DateTimeZone.forID("CST6CDT"));
System.out.println(time4);
System.out.println(time4.withZone(DateTimeZone.forID("America/Phoenix")));
Output (correct)
2020-02-11T12:23:39.817-06:00
2020-02-11T11:23:39.817-07:00
Hopefully, this will help someone else if they come across the same problem.
I have a problem to convert a java.sql.Time (UTC) which is fetched from a database to a java.time.LocalTime (GMT+1 DST). It is always missing the DST hour. So like a Time of 03:00 is only converted to a LocalTime of 04:00 instead of 05:00.
//Saved UTC time in DB: 03:00
LocalTime.ofInstant(Instant.ofEpochMilli(sqlTime.getTime()), ZoneId.of("Europe/Berlin"));
=> 04:00 //expected 05:00
I guess the problem is that java.sql.Time saves the time with a default date of 1970-01-01 and in 1970 there was no DST in Germany. But of course the time should be shown for today and not for 1970.
So how can I get the correct time for this example?
Assuming that you are using at least JDBC 4.2, you should be able to retrieve a LocalTime from your result set:
LocalTime timeInUtc = yourResultSet.getObject(yourTimeColumn, LocalTime.class);
Then there’s no need bother with the outdated and poorly designed java.sql.Time class. The time you get will still be in UTC, of course. Here’s how to convert:
LocalTime timeInUtc = LocalTime.of(3, 0);
ZoneId zone = ZoneId.of("Europe/Berlin");
LocalTime timeInGermany = OffsetDateTime.now(ZoneOffset.UTC)
.with(timeInUtc)
.atZoneSameInstant(zone)
.toLocalTime();
System.out.println("Zeit heute in Deutschland: " + timeInGermany);
When I ran the code today I got the output you expected:
Zeit heute in Deutschland: 05:00
Edit: If there’s no way you can avoid getting a java.sql.Time, convert it to LocalTime first. Assuming that the Time is in UTC and we don’t want to rely on a fragile JVM time zone setting for conversion, you are correct that we need the getTime method:
Time sqlTimeInUtc = // Get from database
LocalTime timeInUtc
= LocalTime.MIDNIGHT.plus(sqlTimeInUtc.getTime(), ChronoUnit.MILLIS);
If you could rely on the JVM time zone setting also being UTC, the following would be nicer:
LocalTime timeInUtc = sqlTimeInUtc.toLocalTime();
In both cases the rest is as above.
In all cases there are some corner cases around the question whether you want “today in UTC” or “today in Europe/Berlin time zone” when you say “the time should be shown for today”. There’s also a corner case if the time is between 2 and 3 AM and today is the last Sunday in March, where the clocks are turned forward from 2 to 3 to initiate summer time (DST) in Germany. Please think these corner cases through and decide what you want.
By the way your diagnosis is completely correct: Time.getTime returns the time of day on Jan 1, 1970, so when you feed this into an Instant, you are converting the time of day on this date, that is, without summer time.
As far as I understand it your question is: Given a time in UTC convert it to local time according to the current time offset. This time offset is different depending of whether DST is in effect or not.
A possible approach is to determine the current offset using TimeZone:
TimeZone tz = TimeZone.getTimeZone("Europe/Berlin");
int timeZoneOffsetMillis = tz.getOffset(new Date().getTime());
Now timeZoneOffsetMillis contains the number of milliseconds you have to add to your UTC time to get local time.
You can get a LocalTime like this:
LocalTime localTime = LocalTime.ofNanoOfDay((sqlTime.getTime() + timeZoneOffsetMillis) * 1000000L);
If your time is only accurate to seconds instead of nanoseconds anyway you might want to use LocalTime.ofSecondOfDay.
Is there a letter for the milliseconds since 1970 in SimpleDateFormat? I know about the getTime() method but I want to define a date and time pattern containing the milliseconds.
SimpleDateFormat does not have a symbol (letter) for inserting the milliseconds since the beginning of the epoch starting at 1 January 1970 00:00:00 UTC.
Reason: Frankly just inserting the milliseconds since the beginning of the epoch is just inserting the long value returned by Date.getTime(), the value how an instant in time (Date) is represeneted, which is not very useful when your goal is to create a human-readable, formatted date/time string. So I don't see having a symbol for this being justified. You can append this number easily or have its value included as you would with any other simple number.
However, there is an alternative: String.format()
String.format() uses a format string which also supports Date/Time conversions which is very similar to the pattern of SimpleDateFormat.
For example there is a symbol 'H' for the Hour of the day (24-hour clock), 'm' for Month (two digits) etc., so in most cases String.format() can be used instead of SimpleDateFormat.
What you're interested in is also has a symbol: 'Q': Milliseconds since the beginning of the epoch starting at 1 January 1970 00:00:00 UTC.
What's even better, String.format() is flexible enough to accept both long values and Dates as the input parameter for Date/Time conversions.
Usage:
System.out.println(String.format("%tQ", System.currentTimeMillis()));
System.out.println(String.format("%tQ", new Date()));
// Or simply:
System.out.printf("%tQ\n", System.currentTimeMillis());
System.out.printf("%tQ\n", new Date());
// Full date+time+ millis since epoc:
Date d = new Date();
System.out.printf("%tF %tT (%tQ)", d, d, d);
// Or passing the date only once:
System.out.printf("%1$tF %1$tT (%1$tQ)", d);
// Output: "2014-09-05 11:15:58 (1409908558117)"
[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