简体   繁体   中英

Change time zone of exesting date in Java

I want to change the time zone of given date. I use this code, but i dont have the good result. My input is "2020-06-16 14:00:00" time in Europe/Paris, and I wnat to change it to UTC, that means I want to get "2020-06-16 12:00:00", but I get initial result "2020-06-16 14:00:00".

try {
    // Calendar calParis = Calendar.getInstance();
    String heure = "1400";
    Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2020-06-16");

    String hour = heure.substring(0, heure.length() - 2);
    String minute = heure.substring(heure.length() - 2);
    Calendar cal = Calendar.getInstance();
    String datenew = "2020-06-16" + " " + hour + ":" + minute + ":00";
    SimpleDateFormat sdfDatenew = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
    Date thisDate = sdfDatenew.parse(datenew);
    cal.setTime(thisDate);

    cal.setTimeZone(TimeZone.getTimeZone("Europe/UTC"));
    SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
    String dateISO = null;
    dateISO = sdfDate.format(cal.getTime());

    System.out.println("Time in ISO: " + dateISO);

} catch (Exception ex) {

}

Here you go: This way you can get your dates and time in Java-7 format.

public static void main(String[] args) throws ParseException {
        String heure = "1400";
        Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2020-06-16");
        String hour = heure.substring(0, heure.length() - 2);
        String minute = heure.substring(heure.length() - 2);
        String datenew = "2020-06-16" + " " + hour + ":" + minute + ":00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Calendar calendar = Calendar.getInstance();
        Date thisDate = sdf.parse(datenew);
        calendar.setTime(thisDate);
        sdf.setTimeZone(TimeZone.getTimeZone("PDT"));
        System.out.println(sdf.format(calendar.getTime())); // prints 2020-06-16 12:00:00
        sdf.setTimeZone(TimeZone.getDefault());
        System.out.println(sdf.format(calendar.getTime())); // prints 2020-06-16 14:00:00
    }

tl;dr

LocalDateTime
.parse( 
    "2020-06-16 14:00:00"
    .replace( " " , "T" ) 
)
.atZone(
    ZoneId.of( "Europe/Paris" )
)
.toInstant()
.atOffset( ZoneOffset.UTC )
.format(
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" )
)

See this code run live at IdeOne.com .

2020-06-16 12:00:00

java.time

The modern solution uses java.time classes.

Your input string lacks a time zone or offset. So parse as a LocalDateTime object.

LocalDateTime ldt = LocalDateTime.parse( "2020-06-16 14:00:00".replace( " " , "T" ) ) ;

You say with certainty that this string represents a moment as seen in Paris France time zone.

ZoneId zParis = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = ldt.atZone( zParis ) ;

Adjust from there to your target time zone. You happen to want UTC, so just extract an Instant .

Instant instant = zdt.toInstant() ;

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API * , released in March 2014 as part of Java SE 8 standard library.

The answer by Basil Bourque is correct but I would not use String replacement when DateTimeFormatter is capable enough to address this and much more.

Demo:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String input = "2020-06-16 14:00:00";
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(input, dtfInput);
        ZonedDateTime zdtParis = ldt.atZone(ZoneId.of("Europe/Paris"));

        ZonedDateTime zdtUtc = zdtParis.withZoneSameInstant(ZoneId.of("Etc/UTC"));

        // Default format
        System.out.println(zdtUtc);

        // Custom format
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
        String output = dtfOutput.format(zdtUtc);
        System.out.println(output);
    }
}

Output:

2020-06-16T12:00Z[Etc/UTC]
2020-06-16 12:00:00

ONLINE DEMO

All in a single statement:

System.out.println(
        LocalDateTime
        .parse("2020-06-16 14:00:00", DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH))
        .atZone(ZoneId.of("Europe/Paris"))
        .withZoneSameInstant(ZoneId.of("Etc/UTC"))
        .format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH))
);

ONLINE DEMO

Some important notes:

  1. You can use a single pattern, uuuu-MM-dd HH:mm:ss for both of your input and output strings but I prefer using uMd H:m:s for parsing because uuuu-MM-dd HH:mm:ss will fail if you have a year in two digits, a month in single digit, a day-of-month in single digit etc. For parsing, a single u can cater to both, two-digit and four-digit year representation. Similarly, a single M can cater to both one-digit and two-digit month. Similar is the case with other symbols.
  2. Here, you can use y instead of u but I prefer u to y .

Learn more about the modern Date-Time API from Trail: Date Time .


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM