9

I am using the below code to cast time as UTC which is working

import java.text.SimpleDateFormat;
import static java.util.Calendar.* 

def dt = "2018-03-19T06:00:00+01:00"
def format = "yyyy-MM-dd'T'HH:mm:ssX"

TimeZone tz  = TimeZone.getDefault(); //getting up local time zone
TimeZone.setDefault(TimeZone.getTimeZone("UTC")); 
SimpleDateFormat sdf = new SimpleDateFormat(format);      
Date d = sdf.parse(dt);
TimeZone.setDefault(tz);

println d //output: 2018-03-19T05:00:00Z

println d.toTimestamp(); //Output: 2018-03-19 06:00:00.0

But when I use TimeZone.setTimeZone(TimeZone.getTimeZone("UTC")); then it not working.

It is working only with TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

Why so?

Update after comments: Outputs needs to be in CET but in UTC

def dt = "2018-03-19T06:00:00+01:00"
def format = "yyyy-MM-dd'T'HH:mm:ssX"
SimpleDateFormat sdf = new SimpleDateFormat(format);      
sdf.setTimeZone(TimeZone.getTimeZone("CET"))
Date d = sdf.parse(dt);

println d
println d.toTimestamp();

​ Output:

Mon Mar 19 05:00:00 UTC 2018
2018-03-19 05:00:00.0
riens
  • 45
  • 3
Hary
  • 5,690
  • 7
  • 42
  • 79
  • 1
    What do you mean by "working" and "not working"? I strongly suspect you've misunderstood what a `Date` value actually contains. As your input data contains the UTC offset, the time zone in the SDF is irrelevant. – Jon Skeet Mar 23 '18 at 14:30
  • Your ```d``` is in no way tied to your ```tz``` – jseashell Mar 23 '18 at 14:33
  • 1
    See https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util-date/ for details about java.util.Date, btw. I'd also suggest using java.time if at all possible. – Jon Skeet Mar 23 '18 at 14:33
  • @j.seashell: You can't set a time zone on a `Date`. It's a number of milliseconds since the Unix epoch. – Jon Skeet Mar 23 '18 at 14:33
  • @JonSkeet apologies, edit made – jseashell Mar 23 '18 at 14:33
  • Please check outputs in prinln, timestamp shouldn't be in UTC as well? – Hary Mar 23 '18 at 14:34
  • 1
    @JonSkeet Input `2018-03-19T06:00:00+01:00` is in CET format date right?? not UTC – Hary Mar 23 '18 at 14:48
  • Maybe this will help? https://stackoverflow.com/questions/13470830/how-to-change-timezone-for-a-java-util-calendar-date – Sean Mar 23 '18 at 14:52
  • 2
    Firstly, a "format" isn't the same as a time zone. All we know about the value is that it has an offset of UTC+1. But note that 2018-03-19T06:00:00+01:00 and 2018-03-19 05:00:00.0 (UTC) are the same value. It's really unclear at this point what you want - half the time you say you want UTC, and the other half of the time you say you want CET. But a `Date` is neither - it's just an instant in time. If you want a value converted with a given format and with respect to a given time zone, use `SimpleDateFormat.format`... or better, use `java.time` and format with that instead. – Jon Skeet Mar 23 '18 at 15:20
  • 1
    you save me) I had been trying to repair not working TimeZone timeZone = TimeZone.getTimeZone("UTC"); dateFormat.setTimeZone(timeZone); several hours. Omg! Thank you! – Georgiy Chebotarev Sep 12 '18 at 11:15

1 Answers1

7

java.time

    String dt = "2018-03-19T06:00:00+01:00";
    OffsetDateTime dateTime = OffsetDateTime.parse(dt);
    System.out.println(dateTime);

This prints

2018-03-19T06:00+01:00

Contrary to the outdated Date class, an OffsetDateTime from java.time, the modern Java date and time API, does contain a UTC offset, as the name also says. I don’t have experience with Groovy, so sorry to have to trust you to translate from my Java code.

If you want to make sure you get a specific time zone regardless of which offset is in the string:

    ZoneId zone = ZoneId.of("Europe/Brussels");
    ZonedDateTime dateTime = OffsetDateTime.parse(dt).atZoneSameInstant(zone);

This time the result is:

2018-03-19T06:00+01:00[Europe/Brussels]

Don’t rely on three letter time zone abbreviations like CET. CET is a common name for the standard time half (the part without summer time/DST) of very many European time zones that generally share time, but have not always done so and tend to disagree on the time when it comes to historic dates. Other three letter abbreviations are ambiguous and thus lead to even more confusion. Always give time zone as region/city, as I did with Europe/Brussels. Of course, pick the city that matches your desired time zone.

If you think you need a java.sql.Timestamp — you may not need that. If using JDBC 4.2 or higher or a similarly modern JPA implementation, it is better to store either an Instant or a LocalDateTime to your database. The choice depends on your exact requirements and the exact datatype of your database column.

    Instant inst = dateTime.toInstant();
    System.out.println(inst);

Output

2018-03-19T05:00:00Z

Instants always print in UTC. If a sufficiently new JDBC driver is unavailable, you may convert to Timestamp in either of two ways:

    System.out.println(Timestamp.from(inst));
    System.out.println(Timestamp.valueOf(dateTime.toLocalDateTime()));

2018-03-19 06:00:00.0
2018-03-19 06:00:00.0

Because my time zone agrees with the time zone in the date-time object, I get the same result from both conversions. In other time zones the result may not be the same, and you will need to take care to pick the correct one.

What went wrong in your code?

When you use SimpleDateFormat for parsing a string with a UTC offset in it, it uses that offset for determining the point in time. In this case it does not use the time zone you have set through setTimeZone for anything. And it doesn’t put any time zone or offset into the Date it returns because a Date cannot contain a time zone. It is just a point in time.

What confuses many is that the result of Date.toString() seems to contain a time zone abbreviation, as UTC in your output Mon Mar 19 05:00:00 UTC 2018. What happens is that toString() uses the JVM’s time zone setting for generating the string. This is why TimeZone.setDefault() affects the output you get: it sets the JVM setting, affecting all programs running in the same JVM. It doesn’t affect the Date object itself, however, only the result of its toString().

The TimeZone, Date and Timestamp classes are long outdated. SimpleDateFormat is too and at the same time notoriously troublesome. I recommend you don’t use those classes at all. java.time is so much nicer to work with.

Link

Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161