Convert LocalDateTime to LocalDateTime in UTC
Asked Answered
U

10

148

Convert LocalDateTime to LocalDateTime in UTC.

LocalDateTime convertToUtc(LocalDateTime date) {

    //do conversion

}

I searched over net. But did not get a solution

Undersexed answered 6/1, 2016 at 5:42 Comment(6)
Did you find the javadoc for LocalDateTime? It says: "This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone."Formica
Your question does not make sense - you should explain the context of this method and what you are trying to achieve. It seems that you have a fundamental misunderstanding of what the various classes of the API represent.Abusive
If you care about time-zones, you need to use ZonedDateTime, which has conversion methods between time-zones withZoneSameLocal() and withZoneSameInstant()Flurried
Ya. I understood. ThanksUndersexed
You can accept one of the below answers if they answered the question.Giblet
This answers the question #34626882Stoffel
F
187

I personally prefer

LocalDateTime.now(ZoneOffset.UTC);

as it is the most readable option.

Filtration answered 10/1, 2018 at 10:16 Comment(4)
Doesn't this create a new time (now)? The original question was about converting a known time to UTCDielectric
How would we convert from LocalDateTime to UTC -7:00Jerboa
This is not the answer of asked question.Ioyal
This answers the question #34626882Stoffel
W
110

LocalDateTime does not contain Zone information. ZonedDatetime does.

If you want to convert LocalDateTime to UTC, you need to wrap by ZonedDateTime fist.

You can convert like the below.

LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.toLocalTime());

ZonedDateTime ldtZoned = ldt.atZone(ZoneId.systemDefault());

ZonedDateTime utcZoned = ldtZoned.withZoneSameInstant(ZoneId.of("UTC"));

System.out.println(utcZoned.toLocalTime());
Wardieu answered 14/7, 2016 at 14:13 Comment(3)
This is correct, though not technically wrapped. ldt.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")) while concise still conveys meaning enough for not needing the zoned instance variable.Blanca
ZoneOffset.UTC is a nice replacement for ZoneI‌​d.of("UTC")Yearwood
For UTC, the OffsetDateTime is more appropriate than ZonedDateTime. Use: OffsetDateTime.now( ZoneOffset.UTC ) or myInstant.atOffset( ZoneOffset.UTC )Cautious
A
79

There is an even simpler way

LocalDateTime.now(Clock.systemUTC())
Aachen answered 1/6, 2016 at 9:20 Comment(3)
Nice, but does not answer the original question.Hijack
This answer converts a UTC date to a LocalDate. The original question was how to convert a LocalDate to a UTC Date.Filmy
How would we convert from LocalDateTime to UTC -7:00Jerboa
G
40

Question?

Looking at the answers and the question, it seems the question has been modified significantly. So to answer the current question:

Convert LocalDateTime to LocalDateTime in UTC.

Timezone?

LocalDateTime does not store any information about the time-zone, it just basically holds the values of year, month, day, hour, minute, second, and smaller units. So an important question is: What is the timezone of the original LocalDateTime? It might as well be UTC already, therefore no conversion has to be made.

System Default Timezone

Considering that you asked the question anyway, you probably meant that the original time is in your system-default timezone and you want to convert it to UTC. Because usually a LocalDateTime object is created by using LocalDateTime.now() which returns the current time in the system-default timezone. In this case, the conversion would be the following:

LocalDateTime convertToUtc(LocalDateTime time) {
    return time.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
}

An example of the conversion process:

2019-02-25 11:39 // [time] original LocalDateTime without a timezone
2019-02-25 11:39 GMT+1 // [atZone] converted to ZonedDateTime (system timezone is Madrid)
2019-02-25 10:39 GMT // [withZoneSameInstant] converted to UTC, still as ZonedDateTime
2019-02-25 10:39 // [toLocalDateTime] losing the timezone information

Explicit Timezone

In any other case, when you explicitly specify the timezone of the time to convert, the conversion would be the following:

LocalDateTime convertToUtc(LocalDateTime time, ZoneId zone) {
    return time.atZone(zone).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
}

An example of the conversion process:

2019-02-25 11:39 // [time] original LocalDateTime without a timezone
2019-02-25 11:39 GMT+2 // [atZone] converted to ZonedDateTime (zone is Europe/Tallinn)
2019-02-25 09:39 GMT // [withZoneSameInstant] converted to UTC, still as ZonedDateTime
2019-02-25 09:39 // [toLocalDateTime] losing the timezone information

The atZone() Method

The result of the atZone() method depends on the time passed as its argument, because it considers all the rules of the timezone, including Daylight Saving Time (DST). In the examples, the time was 25th February, in Europe this means winter time (no DST).

If we were to use a different date, let's say 25th August from last year, the result would be different, considering DST:

2018-08-25 11:39 // [time] original LocalDateTime without a timezone
2018-08-25 11:39 GMT+3 // [atZone] converted to ZonedDateTime (zone is Europe/Tallinn)
2018-08-25 08:39 GMT // [withZoneSameInstant] converted to UTC, still as ZonedDateTime
2018-08-25 08:39 // [toLocalDateTime] losing the timezone information

The GMT time does not change. Therefore the offsets in the other timezones are adjusted. In this example, the summer time of Estonia is GMT+3, and winter time GMT+2.

Also, if you specify a time within the transition of changing clocks back one hour. E.g. October 28th, 2018 03:30 for Estonia, this can mean two different times:

2018-10-28 03:30 GMT+3 // summer time [UTC 2018-10-28 00:30]
2018-10-28 04:00 GMT+3 // clocks are turned back 1 hour [UTC 2018-10-28 01:00]
2018-10-28 03:00 GMT+2 // same as above [UTC 2018-10-28 01:00]
2018-10-28 03:30 GMT+2 // winter time [UTC 2018-10-28 01:30]

Without specifying the offset manually (GMT+2 or GMT+3), the time 03:30 for the timezone Europe/Tallinn can mean two different UTC times, and two different offsets.

Summary

As you can see, the end result depends on the timezone of the time passed as an argument. Because the timezone cannot be extracted from the LocalDateTime object, you have to know yourself which timezone it is coming from in order to convert it to UTC.

Giblet answered 25/2, 2019 at 11:4 Comment(2)
thanks for the info about LocalDateTime doesn't store any info about time-zone! LocalDateTime does not store any information about the time-zone, it just basically holds the values of year, month, day, hour, minute, second, and smaller units.Lankester
Ya, got to knowPeggiepeggir
M
17

Here's a simple little utility class that you can use to convert local date times from zone to zone, including a utility method directly to convert a local date time from the current zone to UTC (with main method so you can run it and see the results of a simple test):

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public final class DateTimeUtil {
    private DateTimeUtil() {
        super();
    }

    public static void main(final String... args) {
        final LocalDateTime now = LocalDateTime.now();
        final LocalDateTime utc = DateTimeUtil.toUtc(now);

        System.out.println("Now: " + now);
        System.out.println("UTC: " + utc);
    }

    public static LocalDateTime toZone(final LocalDateTime time, final ZoneId fromZone, final ZoneId toZone) {
        final ZonedDateTime zonedtime = time.atZone(fromZone);
        final ZonedDateTime converted = zonedtime.withZoneSameInstant(toZone);
        return converted.toLocalDateTime();
    }

    public static LocalDateTime toZone(final LocalDateTime time, final ZoneId toZone) {
        return DateTimeUtil.toZone(time, ZoneId.systemDefault(), toZone);
    }

    public static LocalDateTime toUtc(final LocalDateTime time, final ZoneId fromZone) {
        return DateTimeUtil.toZone(time, fromZone, ZoneOffset.UTC);
    }

    public static LocalDateTime toUtc(final LocalDateTime time) {
        return DateTimeUtil.toUtc(time, ZoneId.systemDefault());
    }
}
Marketable answered 10/1, 2018 at 15:10 Comment(3)
Also add : final LocalDateTime backToLocal = DateTimeUtil.toZone(utc,ZoneOffset.UTC,ZoneId.systemDefault()); System.out.println("Back To Local: " + backToLocal);Blum
You guys will get the below exception if you want to convert LocalDateTime.MIN to UTC LocalDateTime Invalid value for EpochDay (valid values -365243219162 - 365241780471): -365243219163 java.time.DateTimeException: Invalid value for EpochDay (valid values -365243219162 - 365241780471): -365243219163Tito
Best Answer for people who missed considering timezone while designing but were asked to add timezone support as they scaledLiberticide
P
16

Use the below. It takes the local datetime and converts it to UTC using the timezone. You do not need to create it function.

ZonedDateTime nowUTC = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println(nowUTC.toString());

If you need to obtain the LocalDateTime part of the ZonedDateTime then you can use the following.

nowUTC.toLocalDateTime();

Here is a static method i use in my application to insert UTC time in mysql since i cannot add a default value UTC_TIMESTAMP to a datetime column.

public static LocalDateTime getLocalDateTimeInUTC(){
    ZonedDateTime nowUTC = ZonedDateTime.now(ZoneOffset.UTC);

    return nowUTC.toLocalDateTime();
}
Pinky answered 9/2, 2016 at 5:28 Comment(0)
S
14

Try this using this method.

convert your LocalDateTime to ZonedDateTime by using the of method and pass system default time zone or you can use ZoneId of your zone like ZoneId.of("Australia/Sydney");

LocalDateTime convertToUtc(LocalDateTime dateTime) {
  ZonedDateTime dateTimeInMyZone = ZonedDateTime.
                                        of(dateTime, ZoneId.systemDefault());

  return dateTimeInMyZone
                  .withZoneSameInstant(ZoneOffset.UTC)
                  .toLocalDateTime();
  
}

To convert back to your zone local date time use:

LocalDateTime convertFromUtc(LocalDateTime utcDateTime){
    return ZonedDateTime.
            of(utcDateTime, ZoneId.of("UTC"))
            .toOffsetDateTime()
            .atZoneSameInstant(ZoneId.systemDefault())
            .toLocalDateTime();
}
Stoffel answered 14/11, 2020 at 10:26 Comment(0)
E
5

tldr: there is simply no way to do that; if you are trying to do that, you get LocalDateTime wrong.

The reason is that LocalDateTime does not record Time Zone after instances are created. You cannot convert a date time without time zone to another date time based on a specific time zone.

As a matter of fact, LocalDateTime.now() should never be called in production code unless your purpose is getting random results. When you construct a LocalDateTime instance like that, this instance contains date time ONLY based on current server's time zone, which means this piece of code will generate different result if it is running a server with a different time zone config.

LocalDateTime can simplify date calculating. If you want a real universally usable data time, use ZonedDateTime or OffsetDateTime: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html.

Eller answered 15/11, 2016 at 1:50 Comment(1)
LocalDateTime does not record Time Zone, but you may have this knowledge from elsewhere and add this information to your LocalDateTimes before conversion.Colemancolemanite
H
-1

you can implement a helper doing something like that :

public static LocalDateTime convertUTCFRtoUTCZ(LocalDateTime dateTime) {
    ZoneId fr = ZoneId.of("Europe/Paris");
    ZoneId utcZ = ZoneId.of("Z");
    ZonedDateTime frZonedTime = ZonedDateTime.of(dateTime, fr);
    ZonedDateTime utcZonedTime = frZonedTime.withZoneSameInstant(utcZ);
    return utcZonedTime.toLocalDateTime();
}
Hauteloire answered 9/11, 2017 at 10:39 Comment(1)
UTC fr to UTC Z ? doesnt mean anything. UTC = Z, UTC <> frColemancolemanite
U
-2
public static String convertFromGmtToLocal(String gmtDtStr, String dtFormat, TimeZone lclTimeZone) throws Exception{
        if (gmtDtStr == null || gmtDtStr.trim().equals("")) return null;
        SimpleDateFormat format = new SimpleDateFormat(dtFormat);
        format.setTimeZone(getGMTTimeZone());
        Date dt = format.parse(gmtDtStr);
        format.setTimeZone(lclTimeZone);
        return

format.format(dt); }

Unpleasant answered 31/1, 2017 at 18:5 Comment(1)
Please don’t teach the young ones to use the long outdated and notoriously troublesome SimpleDateFormat class. At least not as the first option. And not without any reservation. Today we have so much better in java.time, the modern Java date and time API and its DateTimeFormatter.Circle

© 2022 - 2024 — McMap. All rights reserved.