Java - Convertir la date et l’heure entre les fuseaux horaires

Java - Convertir la date et l'heure entre les fuseaux horaires

timezone

Dans ce tutoriel, nous allons vous montrer quelques exemples (ZonedDateTime (Java 8),Date,Calendar etJoda Time) pour convertir une date et une heure entre différents fuseaux horaires.

Tous les exemples convertiront la date et l'heure de

(UTC+8:00) Asia/Singapore - Singapore Time
Date : 22-1-2015 10:15:55 AM

to

(UTC-5:00) America/New_York - Eastern Standard Time
Date : 21-1-2015 09:15:55 PM

Which to use?
Pour le fuseau horaire, évitez à la foisDate etCalendar

  1. Si vous utilisez JDK> = 8, utilisez le nouveau frameworkjava.time.*.

  2. Si vous utilisez JDK <8, utilisez Joda Time. (Le nouveau framework Java 8java.time.* est inspiré de cette bibliothèque)

1. ZonedDateTime

Utilisez toujours ce nouveau Java 8java.time.ZonedDateTime pour représenter une date et une heure contenant un fuseau horaire.

ZonedDateTimeExample.java

package com.example.date;

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

public class ZonedDateTimeExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) {

        String dateInString = "22-1-2015 10:15:55 AM";
        LocalDateTime ldt = LocalDateTime.parse(dateInString, DateTimeFormatter.ofPattern(DATE_FORMAT));

        ZoneId singaporeZoneId = ZoneId.of("Asia/Singapore");
        System.out.println("TimeZone : " + singaporeZoneId);

        //LocalDateTime + ZoneId = ZonedDateTime
        ZonedDateTime asiaZonedDateTime = ldt.atZone(singaporeZoneId);
        System.out.println("Date (Singapore) : " + asiaZonedDateTime);

        ZoneId newYokZoneId = ZoneId.of("America/New_York");
        System.out.println("TimeZone : " + newYokZoneId);

        ZonedDateTime nyDateTime = asiaZonedDateTime.withZoneSameInstant(newYokZoneId);
        System.out.println("Date (New York) : " + nyDateTime);

        DateTimeFormatter format = DateTimeFormatter.ofPattern(DATE_FORMAT);
        System.out.println("\n---DateTimeFormatter---");
        System.out.println("Date (Singapore) : " + format.format(asiaZonedDateTime));
        System.out.println("Date (New York) : " + format.format(nyDateTime));

    }

}

Sortie

TimeZone : Asia/Singapore
Date (Singapore) : 2015-01-22T10:15:55+08:00[Asia/Singapore]
TimeZone : America/New_York
Date (New York) : 2015-01-21T21:15:55-05:00[America/New_York]

---DateTimeFormatter---
Date (Singapore) : 22-1-2015 10:15:55 AM
Date (New York) : 21-1-2015 09:15:55 PM

Note
Reportez-vous à ceZonedDateTime tutorial pour plus d'exemples de fuseau horaire, de décalage personnalisé et d'heure d'été (DST).

2. Date

Note
Lejava.util.Date n'a pas de concept de fuseau horaire, et ne représente que le nombre de secondes écoulées depuis l'époque Unix - 1970-01-01T00: 00: 00Z. Mais, si vous imprimez l'objet Date directement, l'objet Date sera toujours imprimé avec le fuseau horaire système par défaut. Vérifiez le code source deDate.toString().

2.1 Set a time zone to DateFormat and format the java.util.Date

SimpleDateFormat sdfAmerica = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
sdfAmerica.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String sDateInAmerica = sdfAmerica.format(date);

2.2 Full example

DateExample.java

package com.example.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DateExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date (Singapore) : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat(DATE_FORMAT);
        TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
        sdfAmerica.setTimeZone(tzInAmerica);

        String sDateInAmerica = sdfAmerica.format(date); // Convert to String first
        Date dateInAmerica = formatter.parse(sDateInAmerica); // Create a new Date object

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);
        System.out.println("Date (New York) (String) : " + sDateInAmerica);
        System.out.println("Date (New York) (Object) : " + formatter.format(dateInAmerica));

    }

}

Sortie

TimeZone : Asia/Kuala_Lumpur - Malaysia Time
TimeZone : sun.util.calendar.ZoneInfo[id="Asia/Kuala_Lumpur",...]
Date (Singapore) : 22-1-2015 10:15:55 AM

TimeZone : America/New_York - Eastern Standard Time
TimeZone : sun.util.calendar.ZoneInfo[id="America/New_York",...]
Date (New York) (String) : 21-1-2015 09:15:55 PM
Date (New York) (Object) : 21-1-2015 09:15:55 PM

3. Calendrier

3.1 A Calendar example to set a time zone :

    Calendar calendar = new GregorianCalendar();
    calendar.setTime(date);
    calendar.setTimeZone(tzInAmerica);

Une erreur très courante est d'obtenir lesjava.util.Date directement comme ceci:

    //Wrong, it will display 22-1-2015 10:15:55 AM, time is still in the system default time zone!
    Date dateInAmerican = calendar.getTime());

Dans l'exemple ci-dessus, quel que soit le fuseau horaire que vous définissez dans le calendrier, l'objet Date sera toujours imprimé avec le fuseau horaire système par défaut. (Vérifiez le code source deDate.toString())

3.2 The correct way should be using the DateFormat to format it :

    SimpleDateFormat sdfAmerica = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
    TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
    sdfAmerica.setTimeZone(tzInAmerica);
    sdfAmerica.format(calendar.getTime())

ou obtenez la date viacalendar.get():

    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH); // Jan = 0, dec = 11
    int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
    int hour = calendar.get(Calendar.HOUR); // 12 hour clock
    int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); // 24 hour clock
    int minute = calendar.get(Calendar.MINUTE);
    int second = calendar.get(Calendar.SECOND);
    int ampm = calendar.get(Calendar.AM_PM); //0 = AM , 1 = PM

3.3 Full example

CalendarExample.java

package com.example.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class CalendarExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date (Singapore) : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat(DATE_FORMAT);
        TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
        sdfAmerica.setTimeZone(tzInAmerica);

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.setTimeZone(tzInAmerica);

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);

        //Wrong! It will print the date with the system default time zone
        System.out.println("Date (New York) (Wrong!): " + calendar.getTime());

        //Correct! need formatter
        System.out.println("Date (New York) (Correct!) : " + sdfAmerica.format(calendar.getTime()));

        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH); // Jan = 0, dec = 11
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR); // 12 hour clock
        int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); // 24 hour clock
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        int ampm = calendar.get(Calendar.AM_PM); //0 = AM , 1 = PM

        //Correct
        System.out.println("\nyear \t\t: " + year);
        System.out.println("month \t\t: " + month + 1);
        System.out.println("dayOfMonth \t: " + dayOfMonth);
        System.out.println("hour \t\t: " + hour);
        System.out.println("minute \t\t: " + minute);
        System.out.println("second \t\t: " + second);
        System.out.println("ampm \t\t: " + ampm);

    }

}

Sortie

TimeZone : Asia/Kuala_Lumpur - Malaysia Time
TimeZone : sun.util.calendar.ZoneInfo[id="Asia/Kuala_Lumpur",...]
Date (Singapore) : 22-1-2015 10:15:55 AM

TimeZone : America/New_York - Eastern Standard Time
TimeZone : sun.util.calendar.ZoneInfo[id="America/New_York",...]]
Date (New York) (Wrong!): Thu Jan 22 10:15:55 MYT 2015
Date (New York) (Correct!) : 21-1-2015 09:15:55 PM

year        : 2015
month       : 01
dayOfMonth  : 21
hour        : 9
minute      : 15
second      : 55
ampm        : 1

4. Joda Time

4.1 A Joda Time example to set a time zone :

    DateTime dt = new DateTime(date);
    DateTimeZone dtZone = DateTimeZone.forID("America/New_York");
    DateTime dtus = dt.withZone(dtZone);

Encore une fois, une erreur courante est d'obtenir la date directement comme ceci, le fuseau horaire sera perdu.

    //Output : 22-1-2015 10:15:55 AM
    Date dateInAmerica = dtus.toDate();

La méthode correcte est d'abord convertie en JodaLocalDateTime.

    //Output : 21-1-2015 09:15:55 PM
    Date dateInAmerica = dtus.toLocalDateTime().toDate();

4.2 Full example

JodaTimeExample.java

package com.example.date;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class JodaTimeExample {

    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a";

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date (Singapore) : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat(DATE_FORMAT);
        DateTime dt = new DateTime(date);
        DateTimeZone dtZone = DateTimeZone.forID("America/New_York");
        DateTime dtus = dt.withZone(dtZone);
        TimeZone tzInAmerica = dtZone.toTimeZone();
        Date dateInAmerica = dtus.toLocalDateTime().toDate(); //Convert to LocalDateTime first

        sdfAmerica.setTimeZone(tzInAmerica);

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);
        System.out.println("DateTimeZone : " + dtZone);
        System.out.println("DateTime : " + dtus);

        System.out.println("dateInAmerica (Formatter) : " + formatter.format(dateInAmerica));
        System.out.println("dateInAmerica (Object) : " + dateInAmerica);

    }

}

Sortie

TimeZone : Asia/Kuala_Lumpur - Malaysia Time
TimeZone : sun.util.calendar.ZoneInfo[id="Asia/Kuala_Lumpur",...]
Date (Singapore) : 22-1-2015 10:15:55 AM

TimeZone : America/New_York - Eastern Standard Time
TimeZone : sun.util.calendar.ZoneInfo[id="America/New_York",...]
DateTimeZone : America/New_York
DateTime : 2015-01-21T21:15:55.000-05:00
dateInAmerica (Formatter) : 21-1-2015 09:15:55 PM
dateInAmerica (Object) : Wed Jan 21 21:15:55 MYT 2015

P.S Tested with Joda-time 2.9.4