0

Perhaps this is a fringe requirement, as it was really tricky to find a solution which worked..

I had a zoom meeting which had

"timezone": "Europe/Berlin", "created_at": "2020-11-20T19:35:22Z",

I wanted a Java Date which, which, when inspected or output (SimpleDateFormat) would look like created_at + timezone's offset.

Given that I'm in a different timezone to Berlin, most the routes I tried were doing adjustments of sorts based on the system date which I could not get around.

After much pain, I ended up with this method (Made less generic for the sake of this post). I hope this helps someone, and if there was a much less hacky solution, I'd love to know :)

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Greg Bengis
  • 45
  • 1
  • 9
  • I recommend you don’t use `Date`. That class is poorly designed and long outdated. Instead look into `OffsetDateTime`, `ZonedDateTime` and `ZoneId`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Nov 22 '20 at 20:04

2 Answers2

4

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. I suggest you should stop using them completely and switch to the modern date-time API.

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        ZonedDateTime zdt = ZonedDateTime.parse("2020-11-20T19:35:22Z");
        System.out.println(zdt);

        ZonedDateTime zdtAtBerlin = zdt.withZoneSameInstant(ZoneId.of("Europe/Berlin"));
        System.out.println(zdtAtBerlin);

        // Custom format
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss'created_at'XXX");
        System.out.println(formatter.format(zdtAtBerlin));
    }
}

Output:

2020-11-20T19:35:22Z
2020-11-20T20:35:22+01:00[Europe/Berlin]
2020-11-20T20:35:22created_at+01:00

Learn more about the modern date-time API at Trail: Date Time. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Using the legacy API:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) throws ParseException {
        String dateTimeStr = "2020-11-20T19:35:22Z";
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
        Date date = sdf.parse(dateTimeStr);
        System.out.println(sdf.format(date));
        sdf.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
        System.out.println(sdf.format(date));

        // Some other format
        DateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'created_at'XXX");
        sdf2.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
        System.out.println(sdf2.format(date));
    }
}

Output:

2020-11-20T19:35:22Z
2020-11-20T20:35:22+01
2020-11-20T20:35:22created_at+01:00

Note that you should not hardcode 'Z' in the format. This 'Z' stands for Zulu and represents date-time in UTC.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
-1
public static Date adjustDateTimeZone(String created_at, String timezone) throws ParseException {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    Date date = dateFormat.parse(created_at); //parse the date provided by Zoom
    Instant nowUtc = Instant.parse(Constants.dateFormat.format(date)); //Don't create using date.getMillis(). Because there are some weird adjustments that happen.
    ZoneId timezoneId = ZoneId.of(timezone);
    ZonedDateTime correctedDate = ZonedDateTime.ofInstant(nowUtc, timezoneId);
    //An example online showed using ZonedDateTime, and DateFormatter, but it did weird ass adjustments as well, which did not correspond to the 'toString()' output, 
    // which was correct.
    //Therefor I grabbed the twoString() output and created a date from that.
    return new SimpleDateFormat("yyyy-MM-ddHH:mm:ss").parse(correctedDate.toString().substring(0, 19).replaceAll("T", ""));
}
Greg Bengis
  • 45
  • 1
  • 9