0

I am trying to convert time zone, but it's adding one day extra from java function.

   ""  deActivationDate=2021-06-25T23:59:59.000+0000"";
    
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

    try {
        Date date =formatter.parse(deActivationDate);
        deActivationDate=formatter.format(date);
        LOGGER.info("time format  printing 1" +deActivationDate);//2021-06-26T04:29:59.000+0430

        deActivationDate = deActivationDate.substring(0, deActivationDate.length()-2)+":30";

        LOGGER.info("time format  printing 2" +deActivationDate);//2021-06-26T04:29:59.000+04:30""

In above deactivation date is 25 when I am giving input but after formater parase method its converting as 26 why one day os getting add how to avoid it.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
user3595078
  • 273
  • 3
  • 17

3 Answers3

1

java.time through ThreeTen Backport

You should seriously consider using java.time, the modern Java date and time API, for your non-trivial date and time work.

It’s not very clear from your question, but I think that you want to convert the date and time string to the same date and wall-clock time in your own time zone, in this case, Asia/Tehran time zone. So a different point in time: near the end of the day in Iran rather than near the end of the day in UTC. And with a colon in the UTC offset.

I am declaring two formatters, one for parsing without colon and one for formatting back with colon:

private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .appendPattern("xx")
        .toFormatter();

private static final DateTimeFormatter PRINTER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .appendPattern("xxx")
        .toFormatter();

Now your conversion goes like this:

    String deActivationDate = "2021-06-25T23:59:59.000+0000";
    
    OffsetDateTime dateTime = OffsetDateTime.parse(deActivationDate, PARSER);
    deActivationDate = dateTime.atZoneSimilarLocal(ZoneId.systemDefault())
            .format(PRINTER);
    System.out.println("time format  printing: " +deActivationDate);

Output is — tested on Java 1.7.0_67 with ThreeTen Backport version 1.3.6:

time format printing: 2021-06-25T23:59:59+04:30

Java knows that Asia/Tehran time zone uses summer time (DST) on June 25, so converts to and prints your desired offset of +04:30. Had the date been in the standard time part of the year, +03:30 would have been printed instead.

The 0 milliseconds are not printed, which for most purposes is an advantage. The format is ISO 8601, and according to the ISO 8601 standard the fraction of second is optional when it is 0. If you require the millis to be there, use this simpler formatter instead:

private static final DateTimeFormatter PRINTER
        = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx");

time format printing: 2021-06-25T23:59:59.000+04:30

Half-open: You should not represent the end of the day by 1 second before the start of the new day. First, it’s wrong: the day does not end a second before it ends. Second, it may give rise to errors because of times that fall within that last second and therefore in your program will neither belong to one day or the other. Even if this does not happen in practice, you will have programmers wasting their time wondering whether it may happen. Instead represent the end of the day as the first moment of the following day exclusive (typically 00:00). When testing, require a time to be strictly before the end of the day to belong to the day. This approach is standard for all kinds of intervals and certainly for time intervals. They are then known as half-open intervals.

Question: Doesn’t java.time require Java 8?

java.time works nicely on Java 7. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    I strongly recommend this answer for anyone using Java 6+. This will make the code easily portable while upgrading to a higher version of Java in future. – Arvind Kumar Avinash Jun 10 '21 at 18:24
0

Here's the fix for your code. Though we recommend not to do it via substring method.

String deActivationDate="2021-06-25T23:59:59.000+0000";
 
try {
  SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
  formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
  Date date =formatter.parse(deActivationDate);
  deActivationDate=formatter.format(date);
  
  System.out.println("time format  printing 1: " +deActivationDate); 
  //2021-06-25T23:59:59.000+0000

  deActivationDate = deActivationDate.substring(0, 
  deActivationDate.length()-4)+"0430";
    
  System.out.println("time format  printing 2: " +deActivationDate); 
  //2021-06-25T23:59:59.000+0430

} catch (Exception e) {
  System.err.println(e.getMessage());
}
Beshambher Chaukhwan
  • 1,418
  • 2
  • 9
  • 13
  • you are very much correct but after some time timezone will change to 03:30 so we don't want to change manually in code that is the reason we have not added substring – user3595078 Jun 10 '21 at 10:05
  • Check this https://stackoverflow.com/questions/2873119/changing-timezone-without-changing-time-in-java – Beshambher Chaukhwan Jun 10 '21 at 10:06
0

Thanks to all for your suggestion @beshambher-chaukhwan m i have achieved changes with below code

String deActivationDate="2021-06-25T23:59:59.000+0000";
                         
                         SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
                         
                        try {
                            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
                            Date date =formatter.parse(deActivationDate);
                            deActivationDate=formatter.format(date);                    
                            if(TimeZone.getDefault().useDaylightTime()) {
                                  deActivationDate = deActivationDate.substring(0, deActivationDate.length()-4)+"04:30";
                            }else {         
                                  deActivationDate = deActivationDate.substring(0, deActivationDate.length()-4)+"03:30";
                            }
user3595078
  • 273
  • 3
  • 17
  • The answer is not correct. It prints `+04:30` all year. Iran will go back to standard time and offset +03:30 on September 22, 2021. I tried your code with the string `2021-11-25T23:59:59.000+0000` and still got `time format printing 1: 2021-11-25T23:59:59.000+04:30`. The `useDaylightTime` method only tell you *that* the time zone use daylight saving time (summer time), not *in which part of the year* is does, so it returns true always. – Ole V.V. Jun 10 '21 at 18:25