parse exception in java - java

I am trying to validate a string whether it is in ISO-8601 date or not, but it is throwing a parse exception, not sure where it is going wrong.
try {
String s = "2007-03-01T13:00:00Z";
SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
ft.setLenient(false);
System.out.println(ft.format(ft.parse(s)));
} catch (ParseException e) {
System.out.println(e.getMessage());
}
output is:
Unparseable date: "2007-03-01T10:00:00Z"

I suspect that Z is being interpreted as a time zone so would match -0800 but not a literal Z so you could solve that by quoting: 'Z'.
getErrorOffset should tell you where the problem is.

If you're using Java 7, use the following format string: "yyyy-MM-dd'T'HH:mm:ssXXX"
Note: X is a new code (added in Java 7) that matches ISO 8601 time zone strings; see the API documentation of SimpleDateFormat.

If you want to validate an arbitrary string, you cannot hardcode the "Z" time zone designator, as the validation would fail for a valid ISO8601 time stamp like e.g. "2007-03-01T13:00:00+01".
If you are using Java 6 or earlier, SimpleDateFormat will not support ISO8601 time zone encoding, so you cannot use it to validate time stamps either. With Java 7 or later, you can use new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");.

Your code does not work because the SDF is very limited ad was not aware of ISO 8601 at the time when it was written.
You can take this code:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
public final class JSONDateUtil {
private static final DateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
static {
ISO8601_FORMAT.setLenient(false);
ISO8601_FORMAT.setTimeZone(DateUtils.UTC_TIME_ZONE);
}
public static String toJSON(Date date) {
return ISO8601_FORMAT.format(date);
}
public static String toJSON(long millis) {
return ISO8601_FORMAT.format(millis);
}
public static Date toJava(String date) {
try {
return ISO8601_FORMAT.parse(date);
} catch (ParseException e) {
return null;
}
}
}
Note the timezone, very important.

Joda-Time
FYI, if you used Joda-Time instead of the notoriously troublesome java.util.Date/Calendar classes, you could simply pass that ISO 8601 string straight into a DateTime constructor without the bother of a formatter. Joda-Time uses ISO 8601 as its defaults.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime = new DateTime( "2007-03-01T13:00:00Z", timeZone );
Validation
To determine if your input string was invalid, catch IllegalArgumentException.
java.util.Date
You can even get a java.util.Date back out if need be.
java.util.Date date = dateTime.toDate();

Related

Java Instant.parse cannot validate date

I have an instant field and trying to validate the values in this field using the following approach:
Instant.parse("2021-09-29 09:35:07.531")
However, it throws the error:
java.time.format.DateTimeParseException: Text '2021-09-29
09:35:07.531' could not be parsed at index 10.
So, how can I test if the given Instant date in String format is a valid Instant date?
I am implementing an Import feature and I need to check the date cells. So, the date is normally kept in Instant format in db and for this reason I need to check if the cell date value is a valid Instant date. So, if there is a more proper way, of course I can follow that approach.
I do not use the value, I just need to check if the date is a valid date.
Your Date-Time string does not have timezone information and therefore you can not parse it into an Instant without introducing a timezone. I recommend you parse it into LocalDateTime and use the same for DB work if it is supposed to be used independent of timezones.
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse("2021-09-29 09:35:07.531", dtfInput);
System.out.println(ldt);
}
}
Output:
2021-09-29T09:35:07.531
ONLINE DEMO
How to use LocalDateTime in JDBC?
Given below is a sample code to insert a LocalDateTime into columnfoo (which is of TIMESTAMP type):
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, ldt);
st.executeUpdate();
st.close();
Given below is a sample code to retrieve a LocalDateTime from columnfoo:
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
// Assuming the column index of columnfoo is 1
LocalDateTime ldt = rs.getObject(1, LocalDateTime.class));
System.out.println(ldt);
}
rs.close();
st.close();
In case you want to parse the given Date-Time string into Instant:
As described above, you need to introduce a timezone in order to parse it into an Instant.
Demo:
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
// Change the ZoneId to the applicable one e.g. ZoneId.of("Etc/UTC")
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH)
.withZone(ZoneId.systemDefault());
Instant instant = Instant.from(dtfInput.parse("2021-09-29 09:35:07.531"));
System.out.println(instant);
}
}
Output in my timezone, Europe/London:
2021-09-29T08:35:07.531Z
ONLINE DEMO
Learn more about the modern Date-Time API* from 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. Note that Android 8.0 Oreo already provides support for java.time.
A reference to the time zone is mandatory if you are trying to use the Instant class. So, let's try this:
LocalDateTime.from(DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss.SSS").parse("2021-09-29 09:35:07.351")).atZone(ZoneId.systemDefault()).toInstant();
So, how can I test if the given Instant date in String format is a
valid Instant date?
It is not.
An instant is a (unique) point in time. Your string holds a date and time of day. Without knowing the time zone this may denote some point within a range of 24 or 27 hours — so pretty far from being one point in time.
Edit: I understand that you are importing the string from somewhere, that you cannot decide the format or content of the string, and you need to validate it. You can validate it as a date and time. You basically cannot convert it to an Instant, or at least you only can under assumptions the validity of which I can’t know. For validation I suggest this formatter:
private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter(Locale.ROOT);
The formatter reuses built-in formatters and accepts a variable number of decimals in the seconds, which I think will make sense in many contexts. You know better whether it does in yours.
Validate like this:
String importedDateTimeString = "2021-09-29 09:35:07.531";
try {
LocalDateTime.parse(importedDateTimeString, PARSER);
System.out.format("Valid date and time: %s%n", importedDateTimeString);
} catch (DateTimeParseException dtpe) {
System.out.format("Not a valid date and time: %s. Validation error: %s%n",
importedDateTimeString, dtpe);
}
Output:
Valid date and time: 2021-09-29 09:35:07.531
Original recommendation: So instead use a format that includes offset from UTC. In particular the ISO 8601 format for an instant in UTC is a recommended option for several purposes, like 2021-09-29T01:35:07.531Z.
Link: Wikipedia article: ISO 8601

Converting String to TimeStamp using .valueOf() adds zero at the end of time [duplicate]

The function shown below returns the date, e.g. "Sat Sep 8 00:00 PDT 2010". But I expected to get the date in the following format "yyyy-MM-dd HH:mm". What's wrong in this code?
String date = "2010-08-25";
String time = "00:00";
Also in one laptop the output for,e.g. 23:45 is 11:45. How can I define exactly the 24 format?
private static Date date(final String date,final String time) {
final Calendar calendar = Calendar.getInstance();
String[] ymd = date.split("-");
int year = Integer.parseInt(ymd[0]);
int month = Integer.parseInt(ymd[1]);
int day = Integer.parseInt(ymd[2]);
String[] hm = time.split(":");
int hour = Integer.parseInt(hm[0]);
int minute = Integer.parseInt(hm[1]);
calendar.set(Calendar.YEAR,year);
calendar.set(Calendar.MONTH,month);
calendar.set(Calendar.DAY_OF_MONTH,day);
calendar.set(Calendar.HOUR,hour);
calendar.set(Calendar.MINUTE,minute);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date d = calendar.getTime();
String dateString= dateFormat.format(d);
Date result = null;
try {
result = (Date)dateFormat.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
return result;
}
What's wrong in this code?
You seem to be expecting the returned Date object to know about the format you've parsed it from - it doesn't. It's just an instant in time. When you want a date in a particular format, you use SimpleDateFormat.format, it's as simple as that. (Well, or you use a better library such as Joda Time.)
Think of the Date value as being like an int - an int is just a number; you don't have "an int in hex" or "an int in decimal"... you make that decision when you want to format it. The same is true with Date.
(Likewise a Date isn't associated with a specific calendar, time zone or locale. It's just an instant in time.)
How did you print out the return result? If you simply use System.out.println(date("2010-08-25", "00:00") then you might get Sat Sep 8 00:00 PDT 2010 depending on your current date time format setting in your running machine. But well what you can do is:
Date d = date("2010-08-25", "00:00");
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(d));
Just curious why do you bother with this whole process as you can simple get the result by concatenate your initial date and time string.
just use SimpleDateFormat class
See
date formatting java simpledateformat
The standard library does not support a formatted Date-Time object.
The function shown below returns the date, e.g. "Sat Sep 8 00:00 PDT
2010". But I expected to get the date in the following format
"yyyy-MM-dd HH:mm".
The standard Date-Time classes do not have any attribute to hold the formatting information. Even if some library or custom class promises to do so, it is breaking the Single Responsibility Principle. A Date-Time object is supposed to store the information about Date, Time, Timezone etc., not about the formatting. The only way to represent a Date-Time object in the desired format is by formatting it into a String using a Date-Time parsing/formatting type:
For the modern Date-Time API: java.time.format.DateTimeFormatter
For the legacy Date-Time API: java.text.SimpleDateFormat
About java.util.Date:
A java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
Date date = new Date(); // In your case, it will be Date date = date("2010-08-25", "00:00");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
// sdf.setTimeZone(TimeZone.getTimeZone("America/New_York")); // For a timezone-specific value
String strDate = sdf.format(date);
System.out.println(strDate);
Your function, Date date(String, String) is error-prone.
You can simply combine the date and time string with a separator and then use SimpleDateFormat to parse the combined string e.g. you can combine them with a whitespace character as the separator to use the same SimpleDateFormat shown above.
private static Date date(final String date, final String time) throws ParseException {
return sdf.parse(date + " " + time);
}
Note that using a separator is not a mandatory requirement e.g. you can do it as sdf.parse(date + time) but for this, you need to change the format of sdf to yyyy-MM-ddHH:mm which, although correct, may look confusing.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
public static void main(String[] args) throws ParseException {
Date date = date("2010-08-25", "00:00");
String strDate = sdf.format(date);
System.out.println(strDate);
}
private static Date date(final String date, final String time) throws ParseException {
return sdf.parse(date + " " + time);
}
}
Output:
2010-08-25 00:00
ONLINE DEMO
Switch to java.time API.
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
LocalDateTime ldt = localDateTime("2010-08-25", "00:00");
// Default format i.e. the value of ldt.toString()
System.out.println(ldt);
// Custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ENGLISH);
String strDate = dtf.format(ldt);
System.out.println(strDate);
}
private static LocalDateTime localDateTime(final String date, final String time) {
return LocalDateTime.of(LocalDate.parse(date), LocalTime.parse(time));
}
}
Output:
2010-08-25T00:00
2010-08-25 00:00
ONLINE DEMO
You must have noticed that I have not used DateTimeFormatter for parsing the String date and String time. It is because your date and time strings conform to the ISO 8601 standards. 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.
Learn more about 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.
I'm surprise you are getting different date outputs on the different computers. In theory, SimpleDateFormat pattern "H" is supposed to output the date in a 24h format. Do you get 11:45pm or 11:45am?
Although it should not affect the result, SimpleDateFormat and Calendar are Locale dependent, so you can try to specify the exact locale that you want to use (Locale.US) and see if that makes any difference.
As a final suggestion, if you want, you can also try to use the Joda-Time library (DateTime) to do the date manipulation instead. It makes it significantly easier working with date objects.
DateTime date = new DateTime( 1991, 10, 13, 23, 39, 0);
String dateString = new SimpleDateFormat("yyyy-MM-dd HH:mm").format( date.toDate());
DateTime newDate = DateTime.parse( dateString, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));

Java SimpleDateFormat convert "04:50 PM" to "16:50"

I have a question about converting from 12-hour am/pm format to 24-hour format. I have tried using SimpleDateFormat but encountered some problems.
As you can see, I printed 5 lines of original and converted time, but failed for cases ending with "PM". Note that some inputs are of the 24-hour format and others have the 12-hour am/pm format.
Below is the code I write for the conversion:
static String standardizeTime(String inputTime) throws ParseException {
SimpleDateFormat[] testInputFormat = new SimpleDateFormat[2];
SimpleDateFormat returnFormat = new SimpleDateFormat("HH:mm");
testInputFormat[0] = new SimpleDateFormat("hh:mm aa");
testInputFormat[1] = new SimpleDateFormat("HH:mm");
testInputFormat[0].setLenient(false);
testInputFormat[1].setLenient(false);
Date time;
for (int i = 0; i < testInputFormat.length; i++) {
try {
time = testInputFormat[i].parse(inputTime);
return returnFormat.format(time);
} catch (ParseException e) {
continue;
}
}
return "";
}
What should I change to fix this problem?
This works as expected.
import java.text.SimpleDateFormat;
public class HelloWorld{
public static void main(String []args) throws Exception {
final SimpleDateFormat parser = new SimpleDateFormat("hh:mm aa");
final SimpleDateFormat printer = new SimpleDateFormat("HH:mm");
System.out.println(printer.format(parser.parse("4:07 pm")));
}
}
Your code looks good so I think problem is elsewhere.
I fixed my problem by referring to this post: java.text.ParseException: Unparseable date
The problem is, the default language of my computer is not English, so take Alexander's response as an example. I need to write:
import java.text.SimpleDateFormat;
import java.util.Locale;
public class HelloWorld{
public static void main(String []args) throws Exception {
final SimpleDateFormat parser = new SimpleDateFormat("hh:mm aa", Locale.ENGLISH);
final SimpleDateFormat printer = new SimpleDateFormat("HH:mm");
System.out.println(printer.format(parser.parse("4:07 pm")));
}
}
Note the "Locale.ENGLISH" in parser!
Make sure to use Locale with date/time formatting API whenever the date/time contains letters because different locales have a different representation of letters.
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
DateFormat stfInput = new SimpleDateFormat("h:m a", Locale.ENGLISH);// 12-hour format
DateFormat stfOutput = new SimpleDateFormat("HH:mm", Locale.ENGLISH);// 24-hour format
Date time = stfInput.parse("02:57 AM");
System.out.println(stfOutput.format(time));
time = stfInput.parse("07:05 PM");
System.out.println(stfOutput.format(time));
}
}
Output:
02:57
19:05
Note: java.util date-time classes are outdated and error-prone and so is their formatting API, SimpleDateFormat. I suggest you should stop using them completely and switch to the modern date-time API. Learn more about the modern date-time API at Trail: Date Time.
If you are doing it for your 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 modern date-time API:
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("h:m a", Locale.ENGLISH);// 12-hour format
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);// 24-hour format
LocalTime time = LocalTime.parse("02:57 AM", dtfInput);
System.out.println(time.format(dtfOutput));
time = LocalTime.parse("07:05 PM", dtfInput);
System.out.println(time.format(dtfOutput));
}
}
Output:
02:57
19:05
What should I change to fix this problem?
First and most importantly: I recommend that you use java.time, the modern Java date and time API, for your time work. The date-time classes that you tried to use, SimpleDateFormat and Date, are poorly designed and long outdated. The modern API is so much nicer to work with. The last half of the answer by Arvind Kumar Avinash shows you how. There is no reason for me to repeat it. And yes, Arvind’s code does fix your problem.
What went wrong in your code?
It’s been said that your problem is not providing an English-speaking locale to your formatter. This is part of the truth, but it doesn’t fully explain why 07:05 PM was converted to 07:05 where the correct conversion would have given 19:05.
What happened was that your first input formatter, the one with pattern hh:mm aa, failed at parsing because it used a language where PM would be called something else. Next the second formatter, with pattern HH:mm succeeded in parsing the string. Surprising, isn’t it? I consider it one of the many confusing traits of SimpleDateFormat that it doesn’t necessarily parse the entire string. It parsed the 07:05 part as hour of day and minute. Then it ignored the remainder of the string. In this way you got the result 07:05, which is incorrect, instead of the correct 19:05. This is just one of the reasons why you shouldn’t use SimpleDateFormat at all.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Related questions:
Java SimpleDateFormat throwing ParseException: Unparseable date on Windows but not on Mac [duplicate] about locale for parsing AM an PM. I obviously recommend the answer by Basil Bourque using java.time.
SimpleDateFormat parse(string str) doesn't throw an exception when str = 2011/12/12aaaaaaaaa? about SimpleDateFormat not parsing the entire string. Be inspired by the answer by David using java.time to solve the problem in an easy and straightforward way.
Force SimpleDateFormat to parse the whole string, which seems to me to be similar to yours.
Conversion from 12 hours time to 24 hours time in java. I recommend the answer by Cloud using java.time.

What I am doing wrong when parsing an ISO8601 date time?

I am expecting the test below to pass. Could someone tell me what I am doing wrong here? Most likely I am using a wrong pattern but I can't see what is wrong.
#Test
public void parseDateTest() {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.sss'Z'");
DateTime dt = formatter.parseDateTime("1983-03-06T05:00:03.000Z");
assertEquals("1983-03-06T05:00:03.000Z", dt.toString());
}
FYI dt.toString() does print: 1983-03-06T05:00:00.000Z
Thanks!
P.S.
Please note that on this snippet I rely on the default timezone. This is not production code and how to handle correctly the timezone based on needs is covered by many other questions.
The default time zone is derived from the system property user.timezone. If that is null or is not a valid identifier, then the value of the JDK TimeZone default is converted. If that fails, UTC is used.
This checks to see if "1983-03-06T05:00:03.000Z" is equal to dt.toString(). You say that dt.toString() is equal to "1983-03-06T05:00:00.000Z".
"1983-03-06T05:00:03.000Z" !== "1983-03-06T05:00:00.000Z"
Now the problem is why dt.toString() does not have the correct amount of seconds. Let's look at your DateTimeFormat pattern:
"yyyy-MM-dd'T'HH:mm:ss.sss'Z'"
According to the docs, s is for "second of minute" and S is for "fraction of second" (note the case). This means in your input string, both 03 and 000 are being parsed as seconds (when the later should be fractions) and your DateTime's seconds are being overridden with 00. Try updating this format string:
#Test
public void parseDateTest() {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
DateTime dt = formatter.parseDateTime("1983-03-06T05:00:03.000Z");
assertEquals("1983-03-06T05:00:03.000Z", dt.toString());
}
java.time
Quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time API: java.time API is based on ISO 8601 and therefore you do not need a DateTimeFormatter to parse a date-time string which is already in ISO 8601 format (e.g. your date-time string, 1983-03-06T05:00:03.000Z).
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
class Main {
public static void main(String[] args) {
String strModifiedDate = "1983-03-06T05:00:03.000Z";
Instant instant = Instant.parse(strModifiedDate);
System.out.println(instant);
// It can also be directly parsed into a ZonedDateTime
ZonedDateTime zdt = ZonedDateTime.parse(strModifiedDate);
System.out.println(zdt);
// or even into an OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(strModifiedDate);
System.out.println(odt);
}
}
Output:
1983-03-06T05:00:03Z
1983-03-06T05:00:03Z
1983-03-06T05:00:03Z
Learn more about the modern Date-Time API from Trail: Date Time.
Don't use dt.toString(), use formatter.format(dt) instead. That's what the formatter is for:
#Test
public void parseDateTest() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
LocalDateTime dt = formatter.parse("1983-03-06T05:00:03.000Z", LocalDateTime::from);
assertEquals("1983-03-06T05:00:03.000Z", formatter.format(dt));
}

Custom String from ISO Compliant Date

I am getting a date string as 2014-01-11-T00:00:00Z
I want to convert this date to 20140111 i.e YYYYMMDD it should be a string.
Any standard method/function to achieve above?
java.time
Your date-time string, 2014-01-11-T00:00:00Z is a bit weird as I have never seen such a date-time string where there is a hyphen (-) before T. For this kind of string, the following pattern meets the parsing requirement:
yyyy-M-d-'T'H:m:sXXX
Also, with java.time API, I recommend you replace y with u as explained in this answer. For the output string, you do NOT need to define any pattern as there already exists an inbuilt DateTimeFormatter for this pattern: DateTimeFormatter.BASIC_ISO_DATE.
Demo:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d-'T'H:m:sXXX", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse("2014-01-11-T00:00:00Z", dtfInput);
System.out.println(odt);
String output = odt.toLocalDate().format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(output);
}
}
Output:
2014-01-11T00:00Z
20140111
Note:
Had your date-time string been ISO 8601 compliant, you would NOT have needed to use a DateTimeFormatter object explicitly for parsing i.e. you could have simply parsed it as
OffsetDateTime odt = OffsetDateTime.parse("2014-01-11T00:00:00Z");
The Z in the date-time stands for Zulu which specifies UTC time (that has a timezone offset of +00:00 hours) in ISO 8601 standard. Thus, this solution will also work for a date-time string like 2014-01-11-T00:00:00+02:00 which has a timezone offset of +02:00 hours.
In case, you need a java.util.Date object from this object of OffsetDateTime, you can do so as follows:
Date date = Date.from(odt.toInstant());
Learn more about the the modern date-time API* from Trail: Date Time.
Note that the legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) are outdated and error-prone. It is recommended to stop using them completely and switch to java.time API. Just for the sake of completeness, I am providing you with a solution using the legacy API.
Using the legacy API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String args[]) throws ParseException {
SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-M-d-'T'H:m:sXXX", Locale.ENGLISH);
SimpleDateFormat sdfOutput = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
sdfOutput.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));// Change it as required
Date date = sdfInput.parse("2014-01-11-T00:00:00Z");
String output = sdfOutput.format(date);
System.out.println(output);
}
}
Output:
20140111
* 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.
Take this
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormat {
public static void main(String[] args) throws ParseException {
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-'T'HH:mm:ss'Z'");
Date inDate = inFormat.parse("2014-01-11-T00:00:00Z");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMdd");
String output = outFormat.format(inDate);
System.out.println("Date: " + output);
}
}
Take a look at this thread for Date formatting in Java using Zoulou notation :
Converting ISO 8601-compliant String to java.util.Date
Then create a new SimpleDateFormat using the "yyyyMMdd" format string.
Here an improved version of given answer by #drkunibar:
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-'T'HH:mm:ss'Z'");
inFormat.setTimeZone(TimeZone.getTimeZone("GMT")); // Z denotes UTC in ISO-8601
Date inDate = inFormat.parse("2014-01-11-T00:00:00Z");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMdd");
outFormat.setTimeZone(TimeZone.getTimeZone("...")); // set your timezone explicitly!
String output = outFormat.format(inDate);
System.out.println("Date: " + output);
Note that the format YYYYMMDD is also ISO-8601-compliant (a so-called basic calendar date). The question you have to ask yourself is in which timezone you want to get your output. If in UTC you have to set "GMT", too. Without setting timezone it can happen that your output date differs from input UTC date by one day dependent where your default system timezone is (for example US is several hours behind UTC, in this case one calendar day before UTC midnight).
Update: This Answer is now obsolete. See the modern solution using java.time in the Answer by Avinash.
Joda-Time
This date-time work is much easier with the Joda-Time 2.3 library.
String input = "2014-01-11T00:00:00Z"; // In standard ISO 8601 format.
DateTime dateTime = new DateTime( input, DateTimeZone.UTC ); // Parse string into date-time object.
DateTimeFormatter formatter = ISODateTimeFormat.basicDate(); // Factory to make a formatter.
String output = formatter.print( dateTime ); // Generate string from date-Time object.

Categories

Resources