Date formats difference between yyyy-MM-dd'T'HH:mm:ss and yyyy-MM-dd'T'HH:mm:ssXXX
Asked Answered
C

4

10

I am trying to parse a date 2014-12-03T10:05:59.5646+08:00 using these two formats:

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

When I parse using yyyy-MM-dd'T'HH:mm:ss it works fine, but when I parse yyyy-MM-dd'T'HH:mm:ssXXX a ParseException is thrown.

Which is the correct format to parse the date and also what exactly is the difference between these two formats?

Note : I cannot use Joda :(

Crusty answered 21/9, 2015 at 11:58 Comment(1)
Where did you read that you should use XXX to represent milliseconds? I'm not seeing it anywhere in SimpleDateFormat javadoc.Hargrove
F
8

use this format yyyy-MM-dd'T'HH:mm:ss.SSSSX

From SimpleDateFormat API

//Letter    Date or Time Component  Presentation        Example
  S         Millisecond             Number              978
  X         Time zone               ISO 8601 time zone  -08; -0800; -08:00

USE:

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSX");
String date = "2014-12-03T10:05:59.5646+08:00";
System.out.println(format.parse(date));

OUTPUT:

Wed Dec 03 03:06:04 CET 2014
Frizzell answered 21/9, 2015 at 12:1 Comment(4)
Don't use that format. Read my comment to the first answer.Beutler
@Beutler a) actually first answer is mine. b) this code is working, please check here a working demo c) can you please explain what you mean with example is not valid since the tz offset is not extended ?? thanksFrizzell
I did not say that is not working. The format is invalid. Read on Wikipedia. You have to representations, basic and extended. If you write date and time in extended format, tz offset must be written too. Otherwise the input is not valid.Beutler
@Beutler I don't get your point sorry, actually I don't care about what wiki says.... there are millions of date formats, and all are valids for someone, that's why exists parsers like SimpleDateFormat. So please be clearer, put some links or add your own canonical answer as far as seems you know more than us about this...Frizzell
R
7

Those are valid formats:

yyyy-MM-dd'T'HH:mm:ss.SSSZ       >>>  e.g.: 2001-07-04T12:08:56.235-0700

yyyy-MM-dd'T'HH:mm:ss.SSSXXX     >>>  e.g.: 2001-07-04T12:08:56.235-07:00

Edit:
BTW, "X" refer to the (ISO 8601 time zone)

Ratib answered 21/9, 2015 at 12:4 Comment(2)
the first example is not valid since the tz offset is not extended.Beutler
I just ran it on eclipse for "today" and it produced: 2015-09-21T17:07:56.450+0300Ratib
A
0

When I parse using yyyy-MM-dd'T'HH:mm:ss it works fine, but when I parse yyyy-MM-dd'T'HH:mm:ssXXX a ParseException is thrown.

Which is the correct format to parse the date and also what exactly is the difference between these two formats?

Let's first look into yyyy-MM-dd'T'HH:mm:ss:

Check the following line (emphasis mine) from the documentation:

Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.

So, basically, the format, yyyy-MM-dd'T'HH:mm:ss is considering only up to 2014-12-03T10:05:59 and ignoring the fraction of second and timezone offset information.

What is wrong with yyyy-MM-dd'T'HH:mm:ssXXX?

In this format, you have put the symbol for timezone offset correctly but missed the symbols for fraction of a second.

What is the correct format to parse it using SimpleDateFormat?

The short answer: None

Long answer: SimpleDateFormat can not handle a precision beyond milliseconds (i.e. 3 digits after .) correctly and therefore none of the formats can parse it correctly. The only way to get it correct is by keeping the digits after . up to three digits e.g. 2014-12-03T10:05:59.564+08:00, 2014-12-03T10:05:59.56+08:00 etc. Let's see how SimpleDateFormat will parse 2014-12-03T10:05:59.5646+08:00 erroneously.

SimpleDateFormat considers the digits after . as the number of milliseconds (instead of fraction of a second, the way the modern date-time API considers). Thus, the calculation goes like this:

5646 milliseconds = 5 seconds + 646 milliseconds
2014-12-03T10:05:59 + 5 seconds + 646 milliseconds = 2014-12-03T10:06:04.646

Let's validate it using the code:

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 strDateTime = "2014-12-03T10:05:59.5646+08:00";
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        Date date = sdf.parse(strDateTime);

        sdf.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
        System.out.println(sdf.format(date));
    }
}

Output:

2014-12-03T10:06:04.646+08:00

java.time

With the release of Java SE 8 in March 2014, the outdated and error-prone legacy Date-Time API (java.util Date-Time types and their formatting type, SimpleDateFormat etc.) was supplanted by java.time, the modern Date-Time API*. It is strongly recommended to stop using the legacy API and switch to this new API.

Solution using java.time, the modern API:

import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2014-12-03T10:05:59.5646+08:00");
        System.out.println(odt);
    }
}

Output:

2014-12-03T10:05:59.564600+08:00

Isn't it cool?

The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.

By the way, for any reason, if you need to convert this object of OffsetDateTime to an object of java.util.Date, you can do so as follows:

Date date = Date.from(odt.toInstant());

Learn more about java.time, the modern Date-Time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. 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.

Amok answered 27/5, 2021 at 19:7 Comment(0)
P
0

I have faced a similar issue where I was unable to convert Time Stamp directly in Kotlin

so I wrote the code myself

First by Creating a Data Class to store

Data class TimeAndDate(
    val day : String,
    val month : String,
    val year : String,
    val hours : String,
    val minutes : String
)

Now for converting the String

 //for the type of yyyy-MM-dd'T'HH:mm:ss.SSS
// Here timeStamp is a String in the above format
        fun timeAndDateConverter(timeStamp: String): TimeAndDate {
            val day = timeStamp.subSequence(8, 10).toString()
            val year = timeStamp.subSequence(2, 4).toString()
            var month = timeStamp.subSequence(5, 7).toString()
            when (month) {
                "01" -> month = "Jan"
                "02" -> month = "Feb"
                "03" -> month = "Mar"
                "04" -> month = "Apr"
                "05" -> month = "May"
                "06" -> month = "Jun"
                "07" -> month = "Jul"
                "08" -> month = "Aug"
                "09" -> month = "Sep"
                "10" -> month = "Oct"
                "11" -> month = "Nov"
                "12" -> month = "Dec"

            }
            val hours = timeStamp.subSequence(11, 13).toString()
            val minutes = timeStamp.subSequence(14, 16).toString()

            return TimeAndDate(
                day = day,
                month = month,
                year = year,
                hours = hours,
                minutes = minutes
            )

        }

This function will return the data class from where we can get all individual elements

Postmillennialism answered 8/9, 2021 at 21:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.