2

I have date format like this 2016-11-25T09:29:10.588+01:00

I want to convert this to milliseconds and later while printing I have to again convert milliseconds to "yyyy-MM-dd HH:mm:ss.SSS" this format.

static FastDateFormat alarmDateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS");
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSXXX");
df1.setTimeZone(TimeZone.getTimeZone("UTC"));
String string1 = "2016-11-25T09:29:10.588+01:00";
Date result1 = df1.parse(string1);
long timeStamp = result1.getTime();
System.out.println("timeStamp : " +timeStamp);
String eventTime = alarmDateFormat.format(timeStamp);
System.out.println("AfterConverting : " + eventTime);

Result :

timeStamp : 1480062550588
AfterConverting : 2016-11-25 13:59:10.588

Date is proper but the time is different. I have tried setting timezone to "UTC" but it did't help.

Please note: In Java 8 it works fine with other libraries like Instant and all but we wanted in Java 7.

Jesper
  • 202,709
  • 46
  • 318
  • 350
Harsha G
  • 39
  • 1
  • 4
  • 1
    "i have tried setting timezone also "UTC" but it did't help" - well it should... if you set the time zone for `FastDateFormat`, that is. Please show how you've tried to set the time zone. – Jon Skeet Sep 19 '17 at 12:32
  • df1.setTimeZone(TimeZone.getTimeZone("UTC")); – Harsha G Sep 19 '17 at 12:33
  • 1
    @HarshaG Always update (you can edit) your question with new informations. – timiTao Sep 19 '17 at 12:37
  • What should be the output? 09:29? –  Sep 19 '17 at 12:39
  • @Hugo Yes when we convert back it should give original time 09:29 – Harsha G Sep 19 '17 at 12:45
  • 1
    Well that's setting the time zone in the wrong formatter... – Jon Skeet Sep 19 '17 at 13:08
  • 2
    “In Java 8 it works fine with other libraries like Instant and all but we wanted in Java 7.” So why not just use [**ThreeTen Backport**](http://www.threeten.org/threetenbp/)? It offers the modern Java date and time API, with `Instant` and all, in Java 6 and 7. – Ole V.V. Sep 19 '17 at 13:26
  • 2
    Yes, you *really* should add ThreeTen-Backport to your project. The old legacy date-time classes are a wretched mess, confusing, badly-designed. – Basil Bourque Sep 19 '17 at 14:54

1 Answers1

4

You're calling setTimeZone in df1, but this formatter is used only for parsing, and it won't have any effect in formatting.

To format the date to a specific timezone, you must set it in the other formatter (if you don't set, the formatter uses the JVM default timezone). Also, you don't need to rely on another class such as FastDateFormat, you can simply use another SimpleDateFormat.

But to get exactly the same date/time, you need to use the same offset used in the input (+01:00). Date objects don't keep this information, so you must extract it from the input. One way would be to use substring:

SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSXXX");
String string1 = "2016-11-25T09:29:10.588+01:00";
Date result1 = df1.parse(string1);
long timeStamp = result1.getTime();
System.out.println("timeStamp : " + timeStamp);

// extract the +01:00 offset from the input
String offset = string1.substring(23);
SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
// set the offset in the formatter (so output is converted to it)
df2.setTimeZone(TimeZone.getTimeZone("GMT" + offset));
String eventTime = df2.format(timeStamp);
System.out.println("AfterConverting : " + eventTime);

The output will be:

timeStamp : 1480062550588
AfterConverting : 2016-11-25 09:29:10.588

If you want to keep using FastDateFormat, it's also possible to set the timezone in it:

FastDateFormat f = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS", TimeZone.getTimeZone("GMT" + offset));
String eventTime = f.format(timeStamp);

Java new Date/Time API

The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.

For Java 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).

With this, you can parse the input to a org.threeten.bp.OffsetDateTime and use a org.threeten.bp.format.DateTimeFormatter for the output. In this case, the OffsetDateTime keeps the offset information, so you don't need to set it in the formatter:

OffsetDateTime odt = OffsetDateTime.parse(string1);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println("timeStamp : " + odt.toInstant().toEpochMilli());
System.out.println("AfterConverting : " + odt.format(fmt));

The output is the same:

timeStamp : 1480062550588
AfterConverting : 2016-11-25 09:29:10.588