Java Simpledateformat for Time Zone with a Colon Separator

Java SimpleDateFormat for time zone with a colon separator?

JodaTime's DateTimeFormat to rescue:

String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
DateTimeFormatter dtf = DateTimeFormat.forPattern(pattern);
DateTime dateTime = dtf.parseDateTime(dateString);
System.out.println(dateTime); // 2010-03-01T04:00:00.000-04:00

(time and timezone difference in toString() is just because I'm at GMT-4 and didn't set locale explicitly)

If you want to end up with java.util.Date just use DateTime#toDate():

Date date = dateTime.toDate();

Wait for JDK7 (JSR-310) JSR-310, the referrence implementation is called ThreeTen (hopefully it will make it into Java 8) if you want a better formatter in the standard Java SE API. The current SimpleDateFormat indeed doesn't eat the colon in the timezone notation.

Update: as per the update, you apparently don't need the timezone. This should work with SimpleDateFormat. Just omit it (the Z) in the pattern.

String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = sdf.parse(dateString);
System.out.println(date); // Mon Mar 01 00:00:00 BOT 2010

(which is correct as per my timezone)

Java SimpleDateFormat Timezone offset with minute separated by colon

You can get the timezone offset formatted like +01:00 with the SimpleDateFormat in Java 7 (yyyy-MM-dd'T'HH:mm:ss.SSSXXX), or with the Joda's DateTimeFormat (yyyy-MM-dd'T'HH:mm:ss.SSSZZ).

Formatting ISO 8601 date with a colon seperator

You can always use a StringBuilder:

new StringBuilder(
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.format(date))
.insert(22,':')
.toString();

Java DateTimeFormatter for time zone with an optional colon separator?

This: yyyy-MM-dd'T'HH:mm:ss[XXX][X] seems to work.

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[XXX][X]");
dateTimeFormatter.parse("2015-01-28T10:21:44+0100");
dateTimeFormatter.parse("2015-01-28T10:21:44+01:00");

Android Format date with time zone

You can use Joda Time instead. Its DateTimeFormat has a ZZ format attribute which does what you want.

Link

Big advantage: unlike SimpleDateFormat, DateTimeFormatter is thread safe. Usage:

DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ")
.withLocale(Locale.ENGLISH);

How to parse a Date with TimeZone with and without colon

Interesting question. You can use parseBest.

  String[] test =  {"2015-03-25T09:24:10.000+0530" , "2015-03-25T09:24:10.000+05:30" };
for (String s : test) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS[Z][XXX]");
TemporalAccessor result = formatter.parseBest(s, ZonedDateTime::from, ZonedDateTime::from);
System.out.println(result);
}

This outputs

2015-03-25T09:24:10+05:30
2015-03-25T09:24:10+05:30

Date with Timezone in Java

There is the letter X for ISO 8601 timezone.

import java.text.*;
import java.util.*;

public class TimeZoneTest {

public static void main(final String[] args) throws ParseException {

final DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
final String string = "2014-01-02T23:03:30-05:00";
final Date date = format.parse(string);
System.out.println(date);
}
}

Cannot parse String in ISO 8601 format, lacking colon in offset, to Java 8 Date

tl;dr

Until bug is fixed:

OffsetDateTime.parse( 
"2018-02-13T10:20:12.120+0000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" )
)

When bug is fixed:

OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" )

Details

You are using the wrong classes.

Avoid the troublesome old legacy classes such as Date, Calendar, and SimpleDateFormat. Now supplanted by the java.time classes.

The ZonedDateTime class you used is good, it is part of java.time. But it is intended for a full time zone. Your input string has merely an offset-from-UTC. A full time zone, in contrast, is a collection of offsets in effect for a region at different points in time, past, present, and future. For example, with Daylight Saving Time (DST) in most of North America, the offsets change twice a year growing smaller in the Spring as we shift clocks forward an hour, and restoring to a longer value in the Autumn when we shift clocks back an hour.

OffsetDateTime

For only an offset rather than a time zone, use the OffsetDateTime class.

Your input string complies with the ISO 8601 standard. The java.time classes use the standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.

OffsetDateTime odt = OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" );

Well, that should have worked. Unfortunately, there is a bug in Java 8 (at least up through Java 8 Update 121) where that class fails to parse an offset omitting the colon between hours and minutes. So the bug bites on +0000 but not +00:00. So until a fix arrives, you have a choice of two workarounds: (a) a hack, manipulating the input string, or (b) define an explicit formatting pattern.

The hack: Manipulate the input string to insert the colon.

String input = "2018-02-13T10:20:12.120+0000".replace( "+0000" , "+00:00" );
OffsetDateTime odt = OffsetDateTime.parse( input );

DateTimeFormatter

The more robust workaround is to define and pass a formatting pattern in a DateTimeFormatter object.

String input = "2018-02-13T10:20:12.120+0000" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );

odt.toString(): 2018-02-13T10:20:12.120Z

By the way, here is a tip: I have found that with many protocols and libraries, your life is easier if your offsets always have the colon, always have both hours and minutes (even if minutes are zero), and always use a padding zero (-05:00 rather than -5).

DateTimeFormatterBuilder

For a more flexible formatter, created via DateTimeFormatterBuilder, see this excellent Answer on a duplicate Question.

Instant

If you want to work with values that are always in UTC (and you should), extract an Instant object.

Instant instant = odt.toInstant();

ZonedDateTime

If you want to view that moment through the lens of some region’s wall-clock time, apply a time zone.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

See this code run live at IdeOne.com.

All of this has been covered many times in many Answers for many Questions. Please search Stack Overflow thoroughly before posting. You would have discovered many dozens, if not hundreds, of examples.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, and later

    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

What is the correct pattern for parsing the timezone format with SimpleDateFormat

If you can use Java 7 or newer, you can use the XXX pattern to get the timezone to look like +02:00:

yyyy-MM-dd'T'HH:mm:ssXXX

Otherwise you might have to manipulate the date string to remove the colon from the timezone before parsing it.



Related Topics



Leave a reply



Submit