The old API (with Calendar
and SimpleDateFormat
classes) is outdated and has lots of problems.
You should consider using the newer API's. If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time
and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp
), but the classes and methods names are the same.
If you're working with dates/times that contains an offset, the best choice is to use the OffsetDateTime
class, which represents a date and time with an offset. And it already has a method to parse a String
:
// parse a date string with offset -07:00
String strDate = "2017-06-19T17:50:51.000-07:00";
OffsetDateTime dt = OffsetDateTime.parse(strDate);
System.out.println(dt.toString()); // 2017-06-19T17:50:51-07:00
The output will be:
2017-06-19T17:50:51-07:00
Note that by default, the toString()
method didn't show the fraction-of-seconds, because they're zero. If you want to always show these 3 digits, you can use a DateTimeFormatter
:
// use a formatter to always print fraction-of-second with 3 digits
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000-07:00
In this case, the output will be:
2017-06-19T17:50:51.000-07:00
Testing with different offsets:
// offset +03:00
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000+03:00");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000+03:00
// UTC: "Z" == offset zero (or "+00:00")
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000Z");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000Z
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000+00:00");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000Z
If you still have to use the old API (java.util.Calendar
), you can easily convert it to and from the new classes.
If the java.time
package is available, you can do:
// converting the OffsetDateTime to a Calendar
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000Z");
Calendar c = Calendar.getInstance();
// setting the epoch milli to calendar
c.setTimeInMillis(dt.toInstant().toEpochMilli());
// converting Calendar back to OffsetDateTime (using UTC offset)
dt = OffsetDateTime.ofInstant(c.toInstant(), ZoneOffset.UTC);
// converting Calendar back to OffsetDateTime (using +03:00 offset)
dt = OffsetDateTime.ofInstant(c.toInstant(), ZoneOffset.ofHours(3));
If you're using ThreeTenABP, the method c.toInstant()
won't be available. But you can use org.threeten.bp.DateTimeUtils
class to convert it. So, instead of c.toInstant()
you can use DateTimeUtils.toInstant(c)
:
// conversion for ThreeTenABP
// converting Calendar back to OffsetDateTime (using UTC offset)
dt = OffsetDateTime.ofInstant(DateTimeUtils.toInstant(c), ZoneOffset.UTC);
// converting Calendar back to OffsetDateTime (using +03:00 offset)
dt = OffsetDateTime.ofInstant(DateTimeUtils.toInstant(c), ZoneOffset.ofHours(3));
Update: Youtube API
I checked at Youtube API documentation (not sure if that's what you're using) and in the examples it sets the scheduledStartTime
to a date/time in UTC:
broadcastSnippet.setScheduledStartTime(new DateTime("2024-01-30T00:00:00.000Z"));
According to the docs, this field has the following format:
The date and time that the broadcast is scheduled to start. The value is specified in ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ
) format.
So, we just need to create a formatter to get the String
in this format:
// your date/time, in -07:00 offset
String strDate = "2017-06-19T17:50:51.000-07:00";
OffsetDateTime odt = OffsetDateTime.parse(strDate);
// formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
// convert to UTC
String utc = formatter.format(odt.withOffsetSameInstant(ZoneOffset.UTC));
System.out.println(utc); // 2017-06-20T00:50:51.000Z
The output will be in the same format used in youtube's example:
2017-06-20T00:50:51.000Z