1

I am having Input Date as "2020-10-31T00:00:00Z". i want to parse this Date to get Long milliseconds. Note: Converted milliseconds should be in Sydney Time (ie GMT+11).

FYI,

public static long RegoExpiryDateFormatter(String regoExpiryDate)
    {
        long epoch = 0;

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(TimeZone.getTimeZone("GMT+11"));
        Date date;
        try {
            date = df.parse(regoExpiryDate);
            epoch = date.getTime();
        } catch (ParseException e) {
            System.out.println("Exception is:" + e.getMessage());
            e.printStackTrace();
        }

        System.out.println("Converted regoExpiryDate Timestamp*************** " + epoch);
        return epoch;
    }

Output: 1604062800000 which gives Date as 30/10/2019 by using Epoch Converter, but in input i'm passing 31st as Date. Can anyone please clarify this?

Justin
  • 855
  • 2
  • 11
  • 30
  • 3
    What do you mean by milliseconds should be in Sydney time? A number of milliseconds doesn't and can't have a timezone. – Sweeper Dec 27 '19 at 08:16
  • 1
    And you're almost certainly wanting `Instant.parse` and some means of converting to a `LocalDateTime`. – chrylis -cautiouslyoptimistic- Dec 27 '19 at 08:21
  • Hi @Sweeper, Thanks for your information. I need to send Converted epoch to Salesforce which will accept only the long value , Not Date format. that's why i am converting Date into epoch after setting timezone. Please let me know if i did anything wrong. – Justin Dec 27 '19 at 08:26
  • 1
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. In this case just use `Instant` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Dec 27 '19 at 08:41
  • 1
    It’s a lot easier than you think: `Instant.parse("2020-10-31T00:00:00Z").toEpochMilli()` yields the correct 1604102400000 (@Sweeper is correct that the number is independent of time zones). – Ole V.V. Dec 27 '19 at 09:10
  • 1
    Hi @OleV.V. I have got solution by using Instant.parse(regoDate).toEpochMilli() , really thank you so much. – Justin Dec 27 '19 at 09:20

1 Answers1

6

By doing df.setTimeZone(TimeZone.getTimeZone("GMT+11"));, you are asking the date formatter to interpret your string in the GMT+11 time zone. However, your string shouldn't be interpreted in that timezone. See that Z in the string? That stands for the GMT time zone, so you should have done this instead:

df.setTimeZone(TimeZone.getTimeZone("GMT"));

In fact, your string is in the ISO 8601 format for an Instant (or a "point in time", if you prefer). Therefore, you could just parse it with Instant.parse, and get the number of milliseconds with toEpochMilli:

System.out.println(Instant.parse("2020-10-31T00:00:00Z").toEpochMilli());
// prints 1604102400000

Warning: you shouldn't really use SimpleDateFormat anymore if the Java 8 APIs (i.e. Instant and such) are available. Even if they are not, you should use NodaTime or something like that.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 1
    Sweeper, if you will allow me, I have seen many answers from you that were better than this one. IMHO the two important things we should help this questioner with are (1) not hardcoding `Z` as a literal in the format pattern string (2) getting rid of `SimpleDateFormat`. Feel free to copy my suggestion from the comment under the question into your answer if you like. – Ole V.V. Dec 27 '19 at 12:50
  • @OleV.V. See the edit. Is it better now? Tbh, I don't really know how you can not hardcode `Z`, but still use `SimpleDateFormat`? – Sweeper Dec 27 '19 at 12:56
  • 1
    No matter if using the modern `DateTimeFormatter` or the outdated `SimpleDateFormat` uppercase letter `X` will match `Z` as offset (since Java 7 in case of `SimpleDateFormat`). Thanks for improving. – Ole V.V. Dec 27 '19 at 13:21