Date from ZonedDateTime instant not in utc - java

I am creating date like this:
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
Date.from(now.toInstant());
I need Date object have current time in utc, but when I print date it gives me my local time and not utc time.
I also tried with:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
Date date = Date.from(now.toInstant());
But when I print Date again time is not in utc. Am I doing something wrong when creating Date object. Why above 2 approaches not give me Date that have current time in utc.

Two points:
Avoid the long outdated Date class, in particular when you are already using classes from java.time, the modern Java date and time API.
A Date object hasn’t got and cannot have a time zone in it.
To print offset or time zone
If you need your offset, you need to hold on to your OffsetDateTime (or ZonedDateTime) object:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(now);
On my computer this just printed
2017-11-21T11:53:11.519Z
The Z in the end indicates Zulu time zone, another name for UTC (you may also informally think of it as Zero offset from UTC).
If you would like a more human-readable format, you are right, use a formatter:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println(now.format(formatter));
Depending on your locale and the time, this prints something like
Tuesday, November 21, 2017 11:53:11 AM Z
Again the Z means Zulu time zone, UTC.
Date is not going to help you
A Date is just a point in time. So is the Instant that you use for initializing the date. None of them has got a time zone or offset. The difference here is their toString methods: The Instant is always printed in UTC, the Date usually (always?) in the JVM’s default time zone. The latter confuses many into thinking the Date has a time zone when it hasn’t. See All about java.util.Date.
As I have demonstrated, a formatter may put a time zone or offset into a string when formatting the date-time. This does not in any way modify the date-time object, whether OffsetDateTime, ZonedDateTime, Instant or Date. The long outdated DateFormat class may do the same when formatting a Date. It cannot and will not set a time zone in the Date object since (and I repeat) a Date object cannot have a time zone in it.
Long story short, you have no need for the outdated Date class that I can see.

Related

How to get a Date instance with time of a day at a certain time (like 12:00:00.000) in a specific time zone?

for example, now it is 2020-03-16 11:23:23.121 in Vietnam, but my program is running in the USA, how to get a Date instance which is 2020-03-16 12:00:00.000 in Vietnam, which mean, I keep the year, month, day as the same, but set hour as 12, minute, second and nanosecond as 0, can LocalDateTime play a role?
ZonedDateTime zdt = ZonedDateTime.of(2020, 3, 16, 12, 0, 0, 0, ZoneId.of("Asia/Ho_Chi_Minh"));
ZonedDateTime
From java-8 you can use ZonedDateTime to get the date time from any zone
ZonedDateTime dateTime = ZonedDateTime.now(ZoneId.of("Asia/Ho_Chi_Minh"))
And the you can modify the time to 12:00:00 using with method. Pass the time of day as a LocalTime object obtained by calling LocalTime.of. In the new LocalTime object, the second and the nanosecond default to zero, so no need to pass those arguments to the factory method.
dateTime.with( LocalTime.of( 12 , 0 ) ) //2020-03-16T12:00+07:00[Asia/Ho_Chi_Minh]
Java util Date will not store any time zone information and it just represents a specific instant in time (which is only UTC), with millisecond precision. I will suggest to avoid using legacy util.Date
No, do not use LocalDateTime here
can LocalDateTime play a role?
LocalDateTime cannot represent a moment, as it lacks the context of a time zone or offset-from-UTC. So that is exactly the wrong classs to use here on your Question.
To represent a moment, a specific point on the timeline, use:
Instant (always in UTC)
OffsetDateTime (carries an offset-from-UTC, a number of hours-minutes-seconds)
ZonedDateTime (carries an assigned time zone, named in Continent/Region)
See the correct Answer by Deadpool showing the proper use of ZonedDateTime to solve your problem.
For more info, see What's the difference between Instant and LocalDateTime?

How to convert UTC Time to LocalDateTime by using ZonedDateTime

I have found many way to convert localDateTime to LocalDateTime in UTC.
But I could not find any way to convert UTC time at localDateTime by using ZonedDateTime. Do you know a way to convert it ?
This is what I used to convert it to UTC. I need a vice versa method .
ZonedDateTime zonedDate = ZonedDateTime.of(localDateTime,
ZoneId.systemDefault());
localDateTime.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC)
Don’t use LocalDateTime for a date and time for which you know the UTC offset or time zone. For a date and time in your time zone or another known time zone, use ZonedDateTime. For a date and time for which you know an offset (and here UTC counts as an offset) use OFfsetDateTime.
Why? LocalDateTime (confusing class name) is a date and time without time zone or offset. Not storing the known offset or time zone is throwing away vital data and is an error waiting to happen.
One exception: For a date and time in a known time zone in a further future, do store a LocalDateTime and make sure to store the time zone as a separate ZoneId object. This will allow the offset and/or summer time rules (DST rules) for the time zone to be changed between now and that time (which happens more often than we like to think). Only when time draws near and our Java installation may have been updated with the latest zone rules, can we correctly combine the date-time and the zone and obtain the correct moment in time.
Convert UTC date and time to your time zone
OffsetDateTime utcDateTime = OffsetDateTime.of(2019, 9, 10, 12, 0, 0, 0, ZoneOffset.UTC);
System.out.println("UTC date and time: " + utcDateTime);
ZonedDateTime myDateTime = utcDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("Date and time in the default time zone: " + myDateTime);
After I set my time zone to Asia/Istanbul, this snippet output:
UTC date and time: 2019-09-10T12:00Z
Date and time in the default time zone: 2019-09-10T15:00+03:00[Asia/Istanbul]
Convert from your time zone to UTC
For the opposite conversion I prefer:
OffsetDateTime convertedBackToUtc = myDateTime.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("UTC date and time again: " + convertedBackToUtc);
UTC date and time again: 2019-09-10T12:00Z
Still not using any LocalDateTime.

how to get and format date with timezone

I'am creating a date and store it into database, I want to get current time which is timezone = "Asia/Istanbul" not my local time.
I am creating the date in my local computer, my local timezone is also "Asia/Istanbul".
when i deploy it into my server, server timezone is utc, it is turning to utc everytime.
I have different 2 machine, 2 machines have different timezone so I need to set my data dates with the timezone.
here is what i have done. it is ok in my local computer, but fails on server which is UTC
LocalDateTime localDateTime = LocalDateTime.now();
// it gives my local date time, 2019-07-09T10:30:03.171
// local date is now 1:30 pm, UTC is 3 hours after, it looks ok.
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Asia/Istanbul"));
//2019-07-09T10:30:03.171+03:00[Asia/Istanbul]
// it looks +3. I dont want to see +3, I want the date like 01:30 which is shiefted
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
zonedDateTime.format(formatter);
//2019-07-09T07:30:03.171Z
// zone is disappeared, this is 3 hours before UTC
I expect the date like Asia/Istanbul when i created it.
I wouldn’t use LocalDateTime at all. Use ZonedDateTime throughout to eliminate any and all doubt about the time. Also always pass a ZoneId (if not a Clock) to the now method. This makes your code independent of the time zone settings of the computer and JVM.
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Istanbul"));
System.out.println(zonedDateTime);
2019-07-09T14:14:17.280852+03:00[Asia/Istanbul]
You might have misunderstood the +03:00 part, people sometimes do. It means that the time shown is already 3 hours ahead of UTC. So the point in time shown is equal to 11:14:17 UTC.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(zonedDateTime.format(formatter));
2019-07-09 14:14:17
Your formatter does not include time zone, therefore it’s not shown. But it’s the time in İstanbul.
What went wrong in your code?
I am assuming that the comments in your code are from running on your server in UTC (it’s not perfectly clear) and that you ran the code around 10:30 UTC, the same as 13:30 in İstanbul.
A LocalDateTime is a date and time without time zone and without UTC offset. Its no-arg now method uses the JVM’s time zone setting, in this case UTC, so gives you 10:30 on the day in question. I think that ZonedDateTime.of is wrong here: it takes the 10:30 from the LocalDateTime and İstanbul time zone from the ZoneId object and gives you 10:30 in İstanbul, which is not what you wanted. You had wanted 13:30, AKA 1:30 PM.

How to parse offset it is not specified?

I have time 12:00:00 in format HH:mm:ss.
I know that this time comes from server witch is setup with +3 offset.
If i use SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");, it parses time with regard to device, which can be in a different timezone.
Is there another way to parse it with regard to +3 offset except adding it to the original string?
First, should your server rather send the time in UTC? If clients are everywhere, this would seem more time zone neutral and standardized. However, the way to handle it in code wouldn’t be much different. In any case the server offset form UTC could be constant:
private static final ZoneOffset serverOffset = ZoneOffset.ofHours(3);
In real code you will probably want to make it configurable somehow, though. To parse:
OffsetTime serverTime = LocalTime.parse("12:00:00").atOffset(serverOffset);
System.out.println(serverTime);
This prints
12:00+03:00
Since your time format agrees with LocalTime’s default (ISO 8601), we need no explicit formatter. If a representation of the time with offset is all you need, we’re done. If you need to convert to the user’s local time, to do that reliably you need to decide both a time zone and a date:
LocalTime clientTime = serverTime.atDate(LocalDate.of(2018, Month.JANUARY, 25))
.atZoneSameInstant(ZoneId.of("Indian/Maldives"))
.toLocalTime();
System.out.println(clientTime);
With the chosen day and zone we get
14:00
Please substitute your desired time zone and date.
Just hypothetically, if you knew the user’s offset from UTC, you could use just that:
LocalTime clientTime = serverTime.withOffsetSameInstant(ZoneOffset.of("-08:45"))
.toLocalTime();
The example yields 00:15. However, no one knows when the politicians introduce summer time (DST) or other anomalies in the user’s time zone, so I discourage relying on an offset alone.
And yes, I too am using java.time. SimpleDateFormat is not only long outdated, it is also notoriously troublesome, so java.time is what I warmly recommend.
Set the timezone on your SimpleDateFormat object:
SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("GMT+03:00"));
I recommend you use the Java 8 date and time API (package java.time) instead of the old API, of which SimpleDateFormat is a part.
Using the Java 8 DateTime API:
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("HH:mm:ss");
LocalTime clientLocalTime = LocalTime
.parse("12:00:00", formatter)
// Create an OffsetTime object set to the server's +3 offset zone
.atOffset(ZoneOffset.ofHours(3))
// Convert the time from the server timezone to the client's local timezone.
// This expects the time value to be from the same day,
// otherwise the local timezone offset may be incorrect.
.withOffsetSameInstant(ZoneId.systemDefault().getRules().getOffset(Instant.now()))
// Drop the timezone info - not necessary
.toLocalTime();

How to set Date object to point to different time zone in java

In the code below I have used calendar object to initialize time Zone to GMT and get the time accordingly but when I put back in date object, its automatically converting to my local time zone i.e. IST.
Calendar gmt = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dt=gmt.getTime();
Could anyone suggest a way through which I can retain the GMT format in date object also.
its automatically converting to my local time zone i.e. IST
No it's not. A Date object doesn't have a time zone - it's just an instant in time.
You'll see the system-local time zone if you call toString() on a Date, because that's unfortunately what Date.toString() does... but the time zone is not part of the information stored in a Date.
If you want to see a textual representation of a Date in a particular time zone, use DateFormat and set the time zone that you want to use.
java.time
The other answers are correct. The toString method silently applies your JVM’s current default time zone. This is one of many poor design choices in the old date-time classes. Dump those old classes. Move on to the java.time framework built into Java 8 and later.
An Instant is a moment on the time line in UTC.
Instant now = Instant.now();
Apply a time zone (ZoneId) to an Instant to get a ZonedDateTime.
Why are we bothering to create a ZonedDateTime in UTC if the Instant is already in UTC? Because a ZonedDateTime gives you flexibility in formatting String representations of the date-time values. The java.time.format package does not work with Instant objects.
A subclass of ZoneId, ZoneOffset, has a constant for UTC.
ZonedDateTime zdtUtc = ZonedDateTime.ofInstant( ZoneOffset.UTC );
Adjust into any desired time zone.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = ZonedDateTime.ofInstant( instant , zoneId );
Use proper time zone names
Avoid using 3-4 letter codes for time zones. They are neither standardized nor unique. By IST did you mean India Standard Time or Irish Standard Time?
Use standard time zone names. Most are in the pattern of continent/region. For India, Asia/Kolkata. For Ireland, Europe/Dublin.
The Date class does not represent a timezone. It's toString method uses the default platform time zone to output a human readable timestamp, internally it's just a long.

Categories

Resources