Parsing string to date: Illegal pattern character 'T'. - java

I need to parse a string to date in java. My string has the following format:
2014-09-17T12:00:44.0000000Z
but java throws the following exception when trying to parse such format... java.lang.IllegalArgumentException: Illegal pattern character 'T'.
Any ideas on how to parse that?
Thank you!

Given your input of 2014-09-17T12:00:44.0000000Z, it is not sufficient to escape the letter T only. You also have to handle the trailing Z. But be aware, this Z is NOT a literal, but has the meaning of UTC+00:00 timezone offset according to ISO-8601-standard. So escaping Z is NOT correct.
SimpleDateFormat handles this special char Z by pattern symbol X. So the final solution looks like:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSX");
Date d = sdf.parse("2014-09-17T12:00:44.0000000Z");
System.out.println(d); // output: Wed Sep 17 14:00:44 CEST 2014
Note that the different clock time is right for timezone CEST (toString() uses system timezone), and that the result is equivalent to UTC-time 12:00:44. Furthermore, I had to insert seven symbols S in order to correctly process your input which pretends to have precision down to 100ns (although Java pre 8 can only process milliseconds).

You have to escape the 'T' character:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date parse = format.parse("2014-09-17T12:00:44.0000000Z");
Using Answer to: What is this date format? 2011-08-12T20:17:46.384Z

java.time
It is time for the modern answer: always use java.time, the modern Java date and time API, for your date and time work. When this question was asked, java.time had been out with Java 8 for 7 months. Today (2020) no one should use the SimpleDateFormat class that appears to have been the trouble in the question. It is notoriously troublesome and long outdated.
Using java.time we need no explicit formatter:
String str = "2014-09-17T12:00:44.0000000Z";
Instant i = Instant.parse(str);
System.out.println("As Instant: " + i);
Output is:
As Instant: 2014-09-17T12:00:44Z
Your format is ISO 8601 (link at the bottom). The classes of java.time generally parse ISO 8601 as their default and print ISO 8601 back from their toString methods. In ISO 8601 the fraction of second is optional.
If you need a Date object for a legacy API not yet upgraded to java.time:
Date oldfashionedDate = Date.from(i);
System.out.println("As old-fashioned Date: " + oldfashionedDate);
Output in my time zone:
As old-fashioned Date: Wed Sep 17 14:00:44 CEST 2014
Output will vary by time zone because Date.toString() confusingly takes the JVM’s default time zone and uses it for rendering the string.
What went wrong for you?
You haven’t shown us your code, but we can already tell that a couple of things are wrong:
SimpleDateFormat cannot parse a string with 7 fractional digits on the seconds correctly. It supports only milliseconds, exactly three decimals.
In your format pattern string you need to escape the literal T by enclosing it in single quotes, 'T', or SimpleDateFormat will understand it as a pattern letter, and there is no format pattern letter T. This is what your exception message meant.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601.
Related question: Date object SimpleDateFormat not parsing timestamp string correctly in Java (Android) environment about parsing more than three decimals on the seconds.
Related question: ISO 8601 String to Date/Time object in Android.

Try this.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateClass {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Date d = sdf.parse("2014-09-17T12:00:44.0000000Z");
System.out.println(d); //output Wed Sep 17 12:00:44 IST 2014
}
}

Related

Not able to understand "YYYY-MM-DDTHH:MM:SS" date format

I am trying to parse following date time string
2018-01-30T23:59:59.000
I am not able to understand which standard format it is like UTC or ISO_8601
while parsing in the following manner:
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'HH:MM:SS:MS");
Date date = null;
try {
date = sdf.parse("2018-01-30T23:59:59.000");
} catch (ParseException e) {
e.printStackTrace();
}
But It is throwing following exception:
java.text.ParseException: Unparseable date: "2018-01-30T23:59:59.000"
Any help is appreciated.
See the doc of SimpleDateFormat and try this:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDateTime dateTime = LocalDateTime.parse("2018-01-30T23:59:59.000");
System.out.println(dateTime);
This prints:
2018-01-30T23:59:59
Your string is in ISO 8601 format. UTC or Coordinated Universal Time is not a format, it is a standard time used to define the time the rest of use in our respective time zones.
The date-time classes you were using, SimpleDateFormat and Date, are long outdated and the former in particular notoriously troublesome. I recommend that you instead use java.time, the modern Java date and time API. It is so much nicer to work with.
A LocalDateTime is a date with time of day and without time zone or offset from UTC. Its one-argument parse method parses ISO 8601, which is why no explicit formatter is needed.
What went wrong in your code
Your format pattern string has a number of issues to it. Which is one reason why you should appreciate the above solution without any explicit formatter. The first thing that goes wrong is: Your format pattern string has a colon, :, between seconds and milliseconds, whereas your date-time string has a dot, .. This is why you get the exception.
However, fixing this, your code yields the following Date:
Sun Dec 31 23:00:00 CET 2017
It’s one month off from the expected, and the minutes and seconds are missing. Because:
Uppercase YYYY is for week-based year and only useful with a week number. You need lowercase yyyy for year.
Uppercase DD is for day of year. You need lowercase dd for day of month.
You correctly used uppercase MM for month. Trying the same again for minutes won’t work. Maybe you can guess by now: it’s lowercase mm.
Not surprising you need lowercase ss for seconds.
UsingMS for milliseconds is interesting. SimpleDateFormat takes it as M for month (which we’ve already had twice before) and uppercase S for millisecond. Instead you needed uppercase SSS for the three digits of milliseconds.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Wikipedia article: Coordinated Universal Time on UTC
You need to escape the literal T:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:SS");
See This SO Answer for more examples
Update: Your string is in the format
yyyy-MM-dd'T'HH:mm:ss.SSS
but you are trying to parse it with a completely uppercase format string.
This does not do what you want it to do and you should read the documentation on SimpleDateFormat and the format string placeholders

Using replaceAll function in Java 8 for date and timestamp

I would like to set two different inputs from date and timestamp into a date in UTC at the end. I am not sure if using replaceAll function would work.
Inputs:
string date = "06/04/2019" which the format is "MM/dd/yyyy"
string timestamp = "15/03/2018 15:46:59.000386 PM -05:00" which the format
is "dd/MM/yyyy hh:mm:ss.SSSSSS a XXX"
Output:
"06/04/2019 15:46:59.000386 PM -05:00" then transform it into UTC...
Just to complement the other answer above, you can also parse the LocalDate first, and then join it with OffsetTime to create the OffsetDateTime:
OffsetDateTime timestampOnDate = LocalDate
// parse date (dd/MM/uuuu)
.parse(dateString, dateFormatter)
// join with time and offset (ignores 15/03/2018)
.atTime(OffsetTime.parse(timestampString, timestampFormatter));
OffsetTime.parse will create an object that has the time and offset part (ignoring the date you don't want, in this case, "15/03/2018"), and joining it with a LocalDate produces the desired OffsetDateTime.
Not sure which code is better, though. I guess both are equivalent.
replaceAll might work, but only if the dateString is a valid date - which is checked when parsing. If the date string contains an invalid date, such as 35/99/0000, or a valid date in another format, or even some nonsense text, replaceAll won't complain and the result will be an incorrect string.
But parsing those invalid values as a date will throw an exception, so it's better to handle your data as the types they really represent.
Executive answer: No, String.replaceAll will not work for converting your datetime nor your date to UTC.
Java (and Java 8 and later in particular) has very good support for parsing, handling, converting and formatting dates and times. For example:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
DateTimeFormatter timestampFormatter = DateTimeFormatter
.ofPattern("dd/MM/yyyy hh:mm:ss.SSSSSS a XXX", Locale.ENGLISH);
String dateString = "06/04/2019";
String timestampString = "15/03/2018 03:46:59.000386 PM -05:00";
OffsetDateTime timestampOnDate = OffsetDateTime
.parse(timestampString, timestampFormatter)
.with(LocalDate.parse(dateString, dateFormatter));
System.out.println("Output: " + timestampOnDate.format(timestampFormatter));
System.out.println("Output in UTC: "
+ timestampOnDate.withOffsetSameInstant(ZoneOffset.UTC)
.format(timestampFormatter));
This prints:
Output: 06/04/2019 03:46:59.000386 PM -05:00
Output in UTC: 06/04/2019 08:46:59.000386 PM Z
Your strings and formats didn’t quite make sense, so I have changed them a bit: MM/dd to dd/MM, 15 PM to 03 PM and therefore also HH (for hour of day) to hh (for hour within AM or PM). If these changes were not the correct ones, just make the ones you want instead.
Edit: Of course, if you insist, you may do
timestampString = timestampString.replaceFirst("^\\d{2}/\\d{2}/\\d{4}", dateString);
— to obtain 06/04/2019 03:46:59.000386 PM -05:00 and then parse as before. I consider this code less readable, and it also won’t give you the validation of the date that was in the timestamp string at first. I recommend using the date-time classes for manipulating your date and timestamp as I do in the code example.

Obtaining the ISO 8601 date format, e.g.: 2009-06-15T13:45:30

How do you format your date in ISO 8601? E.g.: 2009-06-15T13:45:30
Is there a standard way of generating it from Java without having to create a DateTimeFormatter with a letter pattern?
I see it used in MS documentation:
Standard Date and Time Format Strings
I think this is the commonly referred to as "ISO" date.
Documented in wikipedia], giving examples such as:
Date: 2017-02-21
Combined date and time in UTC: 2017-02-21T10:26:42+00:00
2017-02-21T10:26:42Z
20170221T102642Z
The one thing to be clear: your examples go without any time zone information; so they should be assumed to be "local time".
In this String, T is just Time component in a standard ISO 8601 date time string represented as <date>T<time>. Wikipedia has a detailed page about this standard format.
In java, you can do this to use it
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
I have used GMT here just for example. You can set the time zone according to your need. To get more information about TimeZone here is the docs link
ISO-8601
A single point in time can be represented by concatenating a complete date expression, the letter T as a delimiter, and a valid time expression. For example, "2007-04-05T14:30".
The format of such date is a local date time of ISO 8601, without the time-zone.1 According to Wikipedia, date and time expressed according to ISO 8601 are:
Date: 2017-02-21
Combined date and time in UTC: 2017-02-21T12:34:46+00:00
2017-02-21T12:34:46Z
20170221T123446Z
...
There're several ways to create strings with such format in Java. In Java 8, the easiest way is to use the built-in parsing pattern of LocalDateTime. The reason why I don't use ZonedDateTime is that the time-zone of this date is unknown.
// str -> date
LocalDateTime d = LocalDateTime.parse("2009-06-15T13:45:30");
// date -> str
String text = d.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
1 ISO 8601: Time zone designators
Easy ways to obtain ISO 8601 in Java:
static void time() {
final DateTimeFormatter fmt = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
OffsetDateTime.now().truncatedTo(ChronoUnit.SECONDS).format(fmt);
Instant.now().atOffset(ZoneOffset.ofHours(1)).truncatedTo(ChronoUnit.SECONDS).format(fmt);
Instant.now().atOffset(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS).format(fmt);
OffsetDateTime.parse("2007-12-03T10:15:30+01:00").format(fmt);
LocalDateTime.parse("2009-06-15T13:45:30").format(fmt);
}

java parsing string to date

I am trying to parse 14th March 2011 to a date in Java for a time converter application... I get 26th Dec 2010... Please help.
import java.util.*;
import java.text.*;
class date {
public static void main(String[] args) {
try {
String timestampOrig = "11/03/14,15:00:00";
SimpleDateFormat inFormat = new SimpleDateFormat("YY/MM/dd','HH:mm:ss");
Date parseDate = inFormat.parse(timestampOrig);
System.out.println("parsed date: " + parseDate.toString());
}
catch(ParseException pe){
}
}
}
output:
parsed date: Sun Dec 26 15:00:00 EST 2010
YY should be yy (in lower case). You can find the list of available characters and their meaning in the documentation.
Out of curiosity, more information about YY, which is for week year, here (not 100% sure what it is to be honest).
java.time
I am providing the modern answer using java.time, the modern Java date and time API (since March 2014).
DateTimeFormatter inFormat = DateTimeFormatter.ofPattern("uu/MM/dd,HH:mm:ss");
String timestampOrig = "11/03/14,15:00:00";
LocalDateTime parsedDateTime = LocalDateTime.parse(timestampOrig, inFormat);
System.out.println("parsed date: " + parsedDateTime.toString());
Output is:
parsed date: 2011-03-14T15:00
I recommend you don’t use SimpleDateFormat and Date. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use LocalDateTime and DateTimeFormatter, both from java.time, the modern Java date and time API. The modern API is so much nicer to work with. And BTW would throw an exception if you tried with YY for year, which I find somewhat more helpful for catching your error.
The quotes around the comma in the format pattern string are optional. I know that the documentation recommends them, but I find the format pattern string more readable without them, so left them out.
What went wrong in your code?
Uppercase Y in the format patterns string is for week based year and only useful with a week number. Apperently SimpleDateFormat wasn’t able to combine your specified month and day of month with the week based year of 2011 and instead just took the first day of the week-based year (this is typical behaviour of SimpleDateFormat, giving you a result that cannot be but wrong and pretending all is well). Assuming your locale is American or similar, week 1 is the week that contains January 1 and begins on the Sunday of the same week, therefore in this case the last Sunday of the previous year, December 26, 2010.
With java.time you may use either lowercase y or u for year. The subtle difference is explained in the question linked to at the bottom. In any case a two-digit year is interpreted into the range from year 2000 through 2099 (there are ways to control the interpretation if you need to).
Links
Oracle tutorial: Date Time explaining how to use java.time.
Question: uuuu versus yyyy in DateTimeFormatter formatting pattern codes in Java?

How to Convert JavaScript Date to Date in Java?

I need to convert JsDate to java.util.Date. I searched but I couldn't find anything. So could you help me with this problem?
Edit: I do this conversion process on GWT screen. I have Datepicker on screen and it gives me JsDate value when I use it's getValue() method. So I'm supposed to put this value into the property of an object which has Date type.
ObjectName.setDate(PickerName.getValue());
I hope my edit will be more clear.
Edit2:
This line is the solution of my problem:
myObject.setDate(new Date((long) myPicker.getValue().getTime()));
The best way of dates conversion is using time in milliseconds, UTC. Both JS Date object and java.util.Date class support conversion to milliseconds (getTime()) and instantiating from milliseconds (using constructor).
You can create a java.util.Date object from the 'time since epoch' value of the JS Date
javascript
var d = new Date().getTime();
java
// get value from client (ajax, form, etc), and construct in Date object
long valueFromClient = ...
Date date = new Date(valueFromClient);
String formatted = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
If people like me are forced to parse a JS-formatted date string (as the result of (new Date()).toString() in JavaScript), here is the SimpleDateFormat spec I used:
DateFormat jsfmt = new SimpleDateFormat("EE MMM d y H:m:s 'GMT'Z (zz)");
If you have control of the producer of the dates, I concur that using timestamps or at least .toUTCString() is definitely more robust.
You may want this:
java:
String jsDate="2013-3-22 10:13:00";
Date javaDate=new SimpleDateFormat("yy-MM-dd HH:mm:ss").parse(jsDate);
System.out.println(javaDate);
ISO 8601 and java.time
ISO 8601 is the international standard for date and time including date and time formats. About any programming language has support for it, including both JavaScript and Java.
In JavaScript produce a string in ISO 8601 format using Date.toISOString(). We don’t need any formatter.
var d = new Date();
var n = d.toISOString();
console.log(n);
The result is somewhat human readable as long as you remember that it’s in UTC, denoted by the trailing Z.
In Java parse the string using Instant.parse(). We don’t need to specify any formatter here either.
String stringFromJavaScript = "2021-07-12T05:54:03.365Z";
Instant inst = Instant.parse(stringFromJavaScript);
System.out.println(inst);
Output:
2021-07-12T05:54:03.365Z
The question asked for a java.util.Date for the result from a date picker. We should avoid using java.util.Date for this both because despite the name a Date does not represent a date and because the Date class is poorly designed and long outdated. For a date without time of day a LocalDate is appropriate:
LocalDate date = inst.atZone(ZoneId.systemDefault()).toLocalDate();
System.out.println(date);
In my time zone the output was:
2021-07-12
The conversion is time zone dependent and will only be correct if the default time zone of the JVM (or which time zone you pass to atZone()) is the same as used by the date picker.
If you do need a Date for a legacy API not yet upgraded to java.time:
Date oldfashionedDate = Date.from(inst);
System.out.println(oldfashionedDate);
Mon Jul 12 07:54:03 CEST 2021
Links
Wikipedia article: ISO 8601
Oracle tutorial: Date Time explaining how to use java.time.
I would suggest using the DateFormat parse method (doc can be found here). It can parse a string representation of a date and return a java.util.Date.
JS Date --
new Date()
Wed Aug 14 2019 14:54:38 GMT+0530 (India Standard Time)
Java Date --
new Date().toISOString()
"2019-08-14T09:25:50.136Z"

Categories

Resources