[java] How to set time zone of a java.util.Date?

I have parsed a java.util.Date from a String but it is setting the local time zone as the time zone of the date object.

The time zone is not specified in the String from which Date is parsed. I want to set a specific time zone of the date object.

How can I do that?

This question is related to java date timezone java.util.date

The answer is


java.util.Calendar is the usual way to handle time zones using just JDK classes. Apache Commons has some further alternatives/utilities that may be helpful. Edit Spong's note reminded me that I've heard really good things about Joda-Time (though I haven't used it myself).


tl;dr

…parsed … from a String … time zone is not specified … I want to set a specific time zone

LocalDateTime.parse( "2018-01-23T01:23:45.123456789" )  // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
    .atZone( ZoneId.of( "Africa/Tunis" ) )              // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.

No Time Zone in j.u.Date

As the other correct answers stated, a java.util.Date has no time zone. It represents UTC/GMT (no time zone offset). Very confusing because its toString method applies the JVM's default time zone when generating a String representation.

Avoid j.u.Date

For this and many other reasons, you should avoid using the built-in java.util.Date & .Calendar & java.text.SimpleDateFormat. They are notoriously troublesome.

Instead use the java.time package bundled with Java 8.

java.time

The java.time classes can represent a moment on the timeline in three ways:

  • UTC (Instant)
  • With an offset (OffsetDateTime with ZoneOffset)
  • With a time zone (ZonedDateTime with ZoneId)

Instant

In java.time, the basic building block is Instant, a moment on the time line in UTC. Use Instant objects for much of your business logic.

Instant instant = Instant.now();

OffsetDateTime

Apply an offset-from-UTC to adjust into some locality’s wall-clock time.

Apply a ZoneOffset to get an OffsetDateTime.

ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );

ZonedDateTime

Better is to apply a time zone, an offset plus the rules for handling anomalies such as Daylight Saving Time (DST).

Apply a ZoneId to an Instant to get a ZonedDateTime. Always specify a proper time zone name. Never use 3-4 abbreviations such as EST or IST that are neither unique nor standardized.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

LocalDateTime

If the input string lacked any indicator of offset or zone, parse as a LocalDateTime.

If you are certain of the intended time zone, assign a ZoneId to produce a ZonedDateTime. See code example above in tl;dr section at top.

Formatted Strings

Call the toString method on any of these three classes to generate a String representing the date-time value in standard ISO 8601 format. The ZonedDateTime class extends standard format by appending the name of the time zone in brackets.

String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]

For other formats use the DateTimeFormatter class. Generally best to let that class generate localized formats using the user’s expected human language and cultural norms. Or you can specify a particular format.


Table of all date-time types in Java, both modern and legacy


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?


Joda-Time

While Joda-Time is still actively maintained, its makers have told us to migrate to java.time as soon as is convenient. I leave this section intact as a reference, but I suggest using the java.time section above instead.

In Joda-Time, a date-time object (DateTime) truly does know its assigned time zone. That means an offset from UTC and the rules and history of that time zone’s Daylight Saving Time (DST) and other such anomalies.

String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );

Call the toString method to generate a String in ISO 8601 format.

String output = dateTimeIndia.toString();

Joda-Time also offers rich capabilities for generating all kinds of other String formats.

If required, you can convert from Joda-Time DateTime to a java.util.Date.

Java.util.Date date = dateTimeIndia.toDate();

Search StackOverflow for "joda date" to find many more examples, some quite detailed.


Actually there is a time zone embedded in a java.util.Date, used for some internal functions (see comments on this Answer). But this internal time zone is not exposed as a property, and cannot be set. This internal time zone is not the one used by the toString method in generating a string representation of the date-time value; instead the JVM’s current default time zone is applied on-the-fly. So, as shorthand, we often say “j.u.Date has no time zone”. Confusing? Yes. Yet another reason to avoid these tired old classes.


Here you be able to get date like "2020-03-11T20:16:17" and return "11/Mar/2020 - 20:16"

 private String transformLocalDateTimeBrazillianUTC(String dateJson) throws  ParseException {
    String localDateTimeFormat = "yyyy-MM-dd'T'HH:mm:ss";
    SimpleDateFormat formatInput = new SimpleDateFormat(localDateTimeFormat);

    //Here is will set the time zone
    formatInput.setTimeZone(TimeZone.getTimeZone("UTC-03"));

    String brazilianFormat = "dd/MMM/yyyy - HH:mm";
    SimpleDateFormat formatOutput = new SimpleDateFormat(brazilianFormat);
    Date date = formatInput.parse(dateJson);
    return formatOutput.format(date);
}

If you must work with only standard JDK classes you can use this:

/**
 * Converts the given <code>date</code> from the <code>fromTimeZone</code> to the
 * <code>toTimeZone</code>.  Since java.util.Date has does not really store time zome
 * information, this actually converts the date to the date that it would be in the
 * other time zone.
 * @param date
 * @param fromTimeZone
 * @param toTimeZone
 * @return
 */
public static Date convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone)
{
    long fromTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, fromTimeZone);
    long toTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, toTimeZone);

    return new Date(date.getTime() + (toTimeZoneOffset - fromTimeZoneOffset));
}

/**
 * Calculates the offset of the <code>timeZone</code> from UTC, factoring in any
 * additional offset due to the time zone being in daylight savings time as of
 * the given <code>date</code>.
 * @param date
 * @param timeZone
 * @return
 */
private static long getTimeZoneUTCAndDSTOffset(Date date, TimeZone timeZone)
{
    long timeZoneDSTOffset = 0;
    if(timeZone.inDaylightTime(date))
    {
        timeZoneDSTOffset = timeZone.getDSTSavings();
    }

    return timeZone.getRawOffset() + timeZoneDSTOffset;
}

Credit goes to this post.


Be aware that java.util.Date objects do not contain any timezone information by themselves - you cannot set the timezone on a Date object. The only thing that a Date object contains is a number of milliseconds since the "epoch" - 1 January 1970, 00:00:00 UTC.

As ZZ Coder shows, you set the timezone on the DateFormat object, to tell it in which timezone you want to display the date and time.


If anyone ever needs this, if you need to convert an XMLGregorianCalendar timezone to your current timezone from UTC, then all you need to do is set the timezone to 0, then call toGregorianCalendar() - it will stay the same timezone, but the Date knows how to convert it to yours, so you can get the data from there.

XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar(
        ((GregorianCalendar)GregorianCalendar.getInstance());
xmlStartTime.setTimezone(0);
GregorianCalendar startCalendar = xmlStartTime.toGregorianCalendar();
Date startDate = startCalendar.getTime();
XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar(startCalendar);
xmlStartTime.setHour(startDate.getHours());
xmlStartTime.setDay(startDate.getDate());
xmlStartTime.setMinute(startDate.getMinutes());
xmlStartTime.setMonth(startDate.getMonth()+1);
xmlStartTime.setTimezone(-startDate.getTimezoneOffset());
xmlStartTime.setSecond(startDate.getSeconds());
xmlStartTime.setYear(startDate.getYear() + 1900);
System.out.println(xmlStartTime.toString());

Result:

2015-08-26T12:02:27.183Z
2015-08-26T14:02:27.183+02:00

Convert the Date to String and do it with SimpleDateFormat.

    SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    readFormat.setTimeZone(TimeZone.getTimeZone("GMT" + timezoneOffset));
    String dateStr = readFormat.format(date);
    SimpleDateFormat writeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    Date date = writeFormat.parse(dateStr);

This code was helpful in an app I'm working on:

    Instant date = null;
    Date sdf = null;
    String formatTemplate = "EEE MMM dd yyyy HH:mm:ss";
    try {
        SimpleDateFormat isoFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss");
        isoFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.of("US/Pacific")));
        sdf = isoFormat.parse(timeAtWhichToMakeAvailable);
        date = sdf.toInstant();

    } catch (Exception e) {
        System.out.println("did not parse: " + timeAtWhichToMakeAvailable);
    }

    LOGGER.info("timeAtWhichToMakeAvailable: " + timeAtWhichToMakeAvailable);
    LOGGER.info("sdf: " + sdf);
    LOGGER.info("parsed to: " + date);

You could also set the timezone at the JVM level

Date date1 = new Date();
System.out.println(date1);

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// or pass in a command line arg: -Duser.timezone="UTC"

Date date2 = new Date();
System.out.println(date2);

output:

Thu Sep 05 10:11:12 EDT 2013
Thu Sep 05 14:11:12 UTC 2013

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to date

How do I format {{$timestamp}} as MM/DD/YYYY in Postman? iOS Swift - Get the Current Local Time and Date Timestamp Typescript Date Type? how to convert current date to YYYY-MM-DD format with angular 2 SQL Server date format yyyymmdd Date to milliseconds and back to date in Swift Check if date is a valid one change the date format in laravel view page Moment js get first and last day of current month How can I convert a date into an integer?

Examples related to timezone

How to set the timezone in Django? How to convert Moment.js date to users local timezone? What does this format means T00:00:00.000Z? How do I get the current timezone name in Postgres 9.3? MySQL JDBC Driver 5.1.33 - Time Zone Issue Python get current time in right timezone Symfony2 and date_default_timezone_get() - It is not safe to rely on the system's timezone settings PHP date() with timezone? How to store a datetime in MySQL with timezone info Java SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") gives timezone as IST

Examples related to java.util.date

How to convert ZonedDateTime to Date? Get the current date in java.sql.Date format Convert java.util.date default format to Timestamp in Java How to subtract X day from a Date object in Java? How to add minutes to my Date Convert java.util.Date to String How to set time zone of a java.util.Date? Calculating the difference between two Java date instances