0

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) {

}
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
sousie_linaro
  • 25
  • 1
  • 5
  • 1
    I found an answer to your question here https://stackoverflow.com/questions/2891361/how-to-set-time-zone-of-a-java-util-date – Joey Zhao Jun 10 '21 at 13:13
  • 1
    Does this answer your question? [How to set time zone of a java.util.Date?](https://stackoverflow.com/questions/2891361/how-to-set-time-zone-of-a-java-util-date) – lepaf78691 Jun 10 '21 at 13:17
  • i test the code SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = isoFormat.parse("2010-05-23T09:01:02"); but it dose not work – sousie_linaro Jun 10 '21 at 13:23
  • it should me return the 2010-05-23T07:01:02 that means hours - 2 – sousie_linaro Jun 10 '21 at 13:24
  • 5
    Can you use `ZonedDateTime` and `ZoneId`? then the solution could be simple. – Procrastinator Jun 10 '21 at 14:21
  • 3
    ... or `OffsetDateTime` and `ZoneOffset.UTC`? That means using `java.time` instead of `java.util.Date` and `java.text.SimpleDateFormat`. – deHaar Jun 10 '21 at 14:22
  • 1
    I recommend you don’t use `Date`, `SimpleDateFormat`, `Calendar` and `TimeZone`. All of those classes are poorly designed and long outdated. Instead use `LocalDate`, `ZoneId` and `ZonedDateTime`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jun 10 '21 at 17:33

3 Answers3

2

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
    }
Procrastinator
  • 2,526
  • 30
  • 27
  • 36
  • 2
    These date-time classes are *terrible*, avoid them. For Java 8 and later, use the built-in *java.time* classes. For Java 6 & 7, use the back-port of *java.time*, *ThreeTen-Backport* library. – Basil Bourque Jun 10 '21 at 16:25
2

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() ;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

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 u-M-d 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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110