amit singh
amit singh

Reputation: 23

How to convert ( String in UTC) Date to milliseconds without disturbing its time zone in java

Consider below string are UTC time and I want equivalent time in milliseconds using java.

String flcDate = "2018-09-07 05:45:00.0";
String geofenceDate = "2018-07-27 08:42:20";

I was trying the below code but it's changing the milliseconds on the basis of in which time zone I am.

public static long stringToMilliSeconds(String string) throws ParseException {

          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
          Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
          TimeZone fromTimeZone = calendar.getTimeZone();
          TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
          calendar.setTimeZone(fromTimeZone);

          calendar.setTime(sdf.parse(string));
          System.out.println(calendar.getTime().toString());


          return calendar.getTime().getTime();
    }

Upvotes: 1

Views: 2264

Answers (3)

Anonymous
Anonymous

Reputation: 86379

java.time

This one should be flexible enough to accept both of your strings:

private static DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE)
        .appendLiteral(' ')
        .append(DateTimeFormatter.ISO_LOCAL_TIME)
        .toFormatter();

public static long stringToMilliseconds(String string) {
    return LocalDateTime.parse(string, FORMATTER)
            .toInstant(ZoneOffset.UTC)
            .toEpochMilli();
}

Demonstration:

    String flcDate = "2018-09-07 05:45:00.0";
    System.out.println(stringToMilliseconds(flcDate)); // 1536299100000
    String geofenceDate = "2018-07-27 08:42:20";
    System.out.println(stringToMilliseconds(geofenceDate)); // 1532680940000

Output is in the comments.

The built-in DateTimeFormatter.ISO_LOCAL_DATE accepts a date string like 2018-09-10. DateTimeFormatter.ISO_LOCAL_TIME accepts a time string like 10:15 or 05:45:00.0. The seconds and fraction of second are optional, and the fraction may be up to 9 decimals. I use a DateTimeFormatterBuilder for building the two formatters into one with a space between the date and the time.

The ‘local’ in LocalDateTime (and other java.time class names) means “without time zone information”, so the use of this class makes sure that no unintended time zone, like your default one, interferes. And the use of ZoneOffset.UTC in the conversion to Instant makes sure we get the time in UTC.

What went wrong in your code?

Despite your time zone operations, your SimpleDateFormat uses your local time zone and therefore produces a point in time of 2018-09-07 05:45:00.0 in your local time zone, not in UTC. After that error is introduced, it propagates through your Calendar object and back out into your return value.

I recommend you don’t use SimpleDateFormat, Calendar and TimeZone at all. Those classes are long outdated, and SimpleDateFormat in particular is notoriously troublesome. Today we have so much better in java.time, the modern Java date and time API.

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

Upvotes: 0

keuleJ
keuleJ

Reputation: 3496

Of course you should use the new java.time* Classes. But if its not possible, try this:

public static long stringToMilliSeconds(String string) throws ParseException {

          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
          sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
          Date date = sdf.parse(string);
          System.out.println(date.getTime());

          return date.getTime();
    }

Upvotes: 1

ernest_k
ernest_k

Reputation: 45339

This uses local date-time and instant to convert the string.

return LocalDateTime.parse("2018-09-07 05:45:00.0", 
                           DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
     .toInstant(ZoneOffset.UTC)
     .toEpochMilli(); //1536299100000

The resulting long represents Epoch milliseconds for the input date/time (UTC time):

Instant.ofEpochMilli(1536299100000L)  ==> 2018-09-07T05:45:00Z

And for the second string, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") can be used as formatter.

Upvotes: 3

Related Questions