Reformatting Dates By using Java [duplicate] - java

This question already has answers here:
Parsing a date’s ordinal indicator ( st, nd, rd, th ) in a date-time string
(5 answers)
Closed 5 years ago.
This is the question i got in an online interview test
Output format is like
20th Oct 2052 converts to 2052-10-20.
6th Jun 1933 converts to 1933-06-06.
Can any one please write a method to return an array of strings where each index i contains the value of dates converted to the format YYYY-MM-DD.
This is the code to Convert 1st March 1984 to 1984-03-01 By using Java
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormattingTest {
public void date(String dateString) throws ParseException {
// This Regular Expression will replace st to blank
String dateString1 = dateString.replaceFirst("[a-zA-Z]{2}", "");
//create Date Format and Parse it based on input
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("d MMMM yyyy");
Date rightNow = simpleDateFormat.parse(dateString1);
// Now create Date format for output type. and format the input
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = dateFormat.format(rightNow);
System.out.println(formattedDate);
}
public static void main(String[] args) throws ParseException {
String dateString = "1st March 1984";
DateFormattingTest t = new DateFormattingTest();
t.date(dateString);
}
}
In the above code input is hard coded String dateString = "1st March 1984";
it gives the correct output
But according to the question input should be array of strings in the form of Day Month Year and out put should return an array of strings in the format YYYY-MM-DD. I wrote the dates() method similar to the date() method in the above code. in the solution main method handling IOException it is pre written main method we are supposed to pass our method in main method to return the output but here my method is handling ParseException which is not handled by main method in the given program so i am getting ParseException handling error so is there any other way of writing function to give the output

"d MMMM yyyy" requires month in local language, try to set SimpleDateFormat's Locale to English. Also, theres no need to delete "st", try "d'st' MMMM yyyy"

Related

How do i get a date object for a specific timezone from a string date in Java? [duplicate]

This question already has answers here:
Convert date string (EST) to Java Date (UTC)
(2 answers)
Convert Calender to Date according to timezone [duplicate]
(1 answer)
Closed 3 days ago.
I have a string with value "25/12/2021" and I want to convert this string into a date format which has a New York timezone.
I am new to Java dates
I tried the below:
SimpleDateFormat zdate = new SimpleDateFormat("dd/MM/yyyy");
zdate.setTimeZone(TimeZone.getTimeZone("America/New_York"));
Date zdate2 = zdate.parse("25/12/2021")
but the zdate2 object has the date in my local timezone rather than the New_York timezone.
What am I doing wrong here?
If you are not forced to use java.util.Date, which itself does not have any zone, you could have your requirement met by implementing with java.time:
You just have to
parse it to a LocalDate, a class only having year, month of year and day of month
append a time of day
append the zone
Here's an example…
public static void main(String[] args) throws ParseException {
// example input
String input = "25/12/2021";
// create a pattern handler for parsing
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uuuu");
// create the zone
ZoneId americaNewYork = ZoneId.of("America/New_York");
// parse the String to a LocalDate, then add time of day and zone
ZonedDateTime result = LocalDate.parse(input, dtf)
.atStartOfDay(americaNewYork);
System.out.println(result);
}
Output:
2021-12-25T00:00-05:00[America/New_York]
Small protest about parse() on time objects, the following is what it really takes to assure creation from String information that parse() methods continually reject !!!
bash-5.1$ javac ZoneParse.java
Note: ZoneParse.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
bash-5.1$ java ZoneParse
24 Dec 2021 13:00:00 GMT
bash-5.1$
It will be something alike the following if safe...
import java.time.*;
public class ZoneParse{
public ZoneParse(){
String[] dt = ("25/12/2021").split("/");
ZonedDateTime ztm = (LocalDate.of(new Integer(dt[2]).intValue(),new Integer(dt[1]).intValue(),new Integer(dt[0]).intValue())).atStartOfDay(ZoneId.systemDefault());
System.out.println((java.util.Date.from( (ztm.withZoneSameInstant((ZoneId)ZoneId.of("America/New_York")).toInstant()))).toGMTString());
}//enconstr
public static void main(String[] args){
new ZoneParse();
}//enmain
}//enclss
NOTE withZoneSameInstant() changes both the time and the zone.
withZoneSameLocal() only retags the time as belonging as another time zone
The updated time library since around java 8 is quicker
This following link is a library with some time assistance under construction avoids parse() as much as possible including a pair of methods of String fill in arguments to create a timedate.
https://drive.google.com/file/d/1gjHmdC-BW0Q2vXiQYmp1rzPU497sybNy/view?usp=share_link
The below erroneous code is because parse() is probably one of the WORST explained methods in the docs, it generally requires a few different pages each of different sections to get any explanation of how to use it.
ZonedDateTime ztm = ZonedDateTime.parse("25/12/2021");
Instant it = (ztm.withZoneSameInstant((ZoneId)ZoneId.of("America/New_York"))).toInstant();
java.util.Date date = java.util.Date.from(it);
SimpleDateFormat zdate = new SimpleDateFormat("dd/MM/yyyy");
zdate.setTimeZone(TimeZone.getTimeZone("America/New_York"));
Date zdate2 = zdate.parse("25/12/2021")
Remember the four 'y' letters in format

How to decode the date in Android? - DATETIMESTAMP [duplicate]

This question already has answers here:
Android: Compare time in this format `yyyy-mm-dd hh:mm:ss` to the current moment
(5 answers)
Conversion of a date to epoch Java [duplicate]
(4 answers)
How to get the current time in YYYY-MM-DD HH:MI:Sec.Millisecond format in Java?
(16 answers)
Closed 2 years ago.
The following code gave me Datetimestamp as [ 2020-07-183 17:07:55.551 ]. The issue is with "Day" in Datetimestamp, which has three digits. How to format currentTimeMillis into the right format for day of month?
public String Datetimesetter(long currentTimeMillis, SimpleDateFormat dateFormat) {
dateFormat = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS.SSS");
// Create a calendar object that will convert the date and time value in milliseconds to date.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(currentTimeMillis);
return dateFormat.format(calendar.getTime());
}
SOLUTION WHICH WORKED FOR ME:
Please visit this link.
This is for the case you are supporting Apps from API level 26 (native support of java.time) or you are willing / allowed to use a backport library of the same functionality.
Then you can use a correct / matching pattern (one that considers three-digit days) like this:
public static void main(String[] args) {
// mock / receive the datetime string
String timestamp = "2020-07-183 17:07:55.551";
// create a formatter using a suitable pattern (NOTE the 3 Ds)
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-DDD HH:mm:ss.SSS");
// parse the String to a LocalDateTime using the formatter defined before
LocalDateTime ldt = LocalDateTime.parse(timestamp, dtf);
// and print its default String representation
System.out.println(ldt);
}
which outputs
2020-07-01T17:07:55.551
So I guess the day of year no. 183 was actually July 1st.
your date format is incorrect
dateFormat = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS.SSS");
change to this
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:MM:SS.SSS");

Convert String With Milliseconds To Date Format In Java [duplicate]

This question already has answers here:
Calendar date to yyyy-MM-dd format in java
(11 answers)
java.util.Date format conversion yyyy-mm-dd to mm-dd-yyyy
(8 answers)
How to get the current time in YYYY-MM-DD HH:MI:Sec.Millisecond format in Java?
(16 answers)
Change the format of Date Java [closed]
(2 answers)
Closed 4 years ago.
I am trying to convert a string with milliseconds (20180510-10:50:58.106) to date in java. However, when I convert it I get the millisecond part but again in the string. I want the same part in date format.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class SimpleDateFormatExample {
public static void main(String[] args) {
String curDate = "20180510-10:50:58.106";
Date SysDateVar = null ;
//SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS");
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS");
//String Todate = format.format(curDate);
//System.out.println("format.parse(curDate)="+Todate);
String abc = null;
try
{
abc = format.format(format.parse(curDate));
System.out.println("SysDateVar ="+abc);
SysDateVar = new Date ((long) (format.parse(curDate)).getTime());
System.out.println("format.parse(curDate)="+ SysDateVar);
}
catch (ParseException e) {
e.printStackTrace();
}
}
}
Output Is :
$javac SimpleDateFormatExample.java
$java -Xmx128M -Xms16M SimpleDateFormatExample
SysDateVar =20180510-10:50:58.106
format.parse(curDate)=Thu May 10 10:50:58 UTC 2018
Variable abc is a string. I want the same output in a Date variable.
When you call System.out.println on a Date object, the toString() method of this Date will be called implictly, and it will return in default format like Thu May 10 10:50:58 UTC 2018.
You need call format.format(date) explictly to get desired output.

Java Simple date format - dd/MM/yy v/s dd/MM/yyyy

I need to parse a String into dd/MM/YY hh:mm:ss format.
Suppose if a String has value 09/06/17 05:59:59 then it should be parsed but if a String has value 09/06/2017 05:59:59 then this is also a valid format and getting parsed but in my requirement, a parse exception should be thrown for the later.
Code:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
String line=" 09/06/17 05:59:59 20170609IT36701706080107 42 103 Output USD 970.20 IT3670";
//String line=" 09/06/2017 05:59:59 20170609IT36701706080107 42 103 Output USD 970.20 IT3670";
String dt=null;
dt=line.substring(1, 19);
SimpleDateFormat org_format = new SimpleDateFormat("dd/MM/YY hh:mm:ss");
SimpleDateFormat tgt_format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
dt=line.substring(1, 19);
System.out.println(dt);
Date date = org_format.parse(dt);
System.out.println(date);
String tgt_date=tgt_format.format(date);
System.out.println(tgt_date);
} catch (ParseException e) {
System.out.println(line);
}
}
}
Problem - In the code, uncommented line variable and commented line variable, both are giving result successfully. but the commented line should throw parsable exception as it's the pattern dd/MM/yyyy, not dd/MM/yy.
fmt.setLenient(false) is not working.
I'm using Java 7. Don't have option to use Java 8 or later so can't use java.time.
Don't have option to use java 8 or later so cant use java.time
The Java 8 date and time classes have been backported to Java 6 and 7, so yes, you can use them in your Java 7. Get ThreeTen Backport. This is also the futureproof investment: if and when eventually you upgrade to Java 8 or 9, you will only have to modify your import declarations and your code will work with the java.time classes.
So I recommend you throw the outdated classes SimpleDateFormat and Date over the shoulder. It’s very typical for SimpleDateFormat to give you a result (very often an incorrect one) in a situation where you would want an exception. As you noted, sometimes org_format.setLenient(false); helps, but not in your case.
Using ThreeTen Backport:
DateTimeFormatter originalFormat = DateTimeFormatter.ofPattern("dd/MM/uu HH:mm:ss");
ParsePosition pos = new ParsePosition(1); // skip leading space
LocalDateTime ldt = LocalDateTime.from(originalFormat.parse(line, pos));
This parses your line with 2-digit year into
2017-01-02 05:59:59
For the line with 4-digit year for which “in my requirement, parse exception should be thrown”, we get
Exception in thread "main" java.time.format.DateTimeParseException:
Text ' 09/06/2017 05:59:59 20170609IT36701706080107 42 103 Output USD
...' could not be parsed at index 9
It says index 9, that’s at the 17 in 2017, that is, exactly where the third digit of the year is when there were only supposed to be two digits.
A couple of points to be aware of:
Use capital HH in the format pattern for hour of day (small hh is for hour with AM or PM, only useful with an AM/PM marler). Use lowercase for the year, either uu or yy (not uppercase YY, it’s for weekbased year, only useful with a week number). BTW, again SimpleDateFormat let you get away with these bugs and will sometimes give you incorrect results; the modern classes will object by throwing an exception.
My code will parse into a year from 2000 through 2099. Please check whether this is what you want. You may want to impose an additional restriction, for example, that the date-time should be in the past and not more than 5 years ago, for enhanced validation. You know better than I.
To convert into your target format:
DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String targetDate = ldt.format(targetFormat);
With the former of your lines the result is
2017-01-02 05:59:59
You can use regex to check if year contains 4 digits and if so throw new ParseException. The program is:
public static void main(String[] args) throws ParseException {
String date = "09/06/17 05:59:59";
if (date.matches("\\d{1,2}[/.-]\\d{1,2}[/.-]\\d{4} .*"))
throw new ParseException("date has wrong format");
else {
}
}
Regex to match any of these date formats
String regex = "^(([0]?[1-9]|1[0-2])/([0-2]?[0-9]|3[0-1])/[1-2]\d{3}) (20|21|22|23|[0-1]?\d{1}):([0-5]?\d{1})$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("09/06/17 05:59:59");
if(matcher.matches()){
//your next code
}

How to get the given date string format(pattern) in java?

I want to get the format of a given date string.
Example: I have a string like 2011-09-27T07:04:21.97-05:00 and the date format of this string is yyyy-MM-dd'T'HH:mm:ss.SSS.
Here I want to find out this date format when I pass string(2011-09-27T07:04:21.97-05:00) to a method which will return the format(yyyy-MM-dd'T'HH:mm:ss.SSS), then later I will format my given date string according to my requirement(like yy-mm--dd or mm/dd/yyyy).
Can any one tell me how can I get it achieved?
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NewClass {
private static final String[] formats = {
"yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd HH:mm:ss",
"MM/dd/yyyy HH:mm:ss", "MM/dd/yyyy'T'HH:mm:ss.SSS'Z'",
"MM/dd/yyyy'T'HH:mm:ss.SSSZ", "MM/dd/yyyy'T'HH:mm:ss.SSS",
"MM/dd/yyyy'T'HH:mm:ssZ", "MM/dd/yyyy'T'HH:mm:ss",
"yyyy:MM:dd HH:mm:ss", "yyyyMMdd", };
/*
* #param args
*/
public static void main(String[] args) {
String yyyyMMdd = "20110917";
parse(yyyyMMdd);
}
public static void parse(String d) {
if (d != null) {
for (String parse : formats) {
SimpleDateFormat sdf = new SimpleDateFormat(parse);
try {
sdf.parse(d);
System.out.println("Printing the value of " + parse);
} catch (ParseException e) {
}
}
}
}
}
you can do like this way, I don't know good way or not but try this
first create the SimpleDateFormat object
SimpleDateFormt sdf = new SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSS");
now when check the date if this will parse in this format then change as per your format
try{
Date date = sdf.parse(yourdate);
sdf.applyPattern("yy-mm--dd or mm/dd/yyyy");
String dateformat = sdf.format(date);
}catch(Exception ex) { // here forgot the exact exception class Parse exception was used
// do something here
}
updated post:
Returning a date format from an unknown format of date string in java
How to convert String to Date without knowing the format?
Parse any date in Java
I think you should try to parse input string with some predefine patterns. The one that works is the one you need. Remember that some patterns are quite tricky.
01.12.12 is 01 December 2012 in Europe but 12 January 2012 in USA. It could be 12 December 2001 too.
If I understand you correctly, you want to parse arbitrary strings (that is, string of a format you don't know) as dates by using DateFormat.parse()? Then you have to deal with issues like how to handle 01-02-03 (2 Jan 2003? 1 Feb 2003? etc.)
You should know at least something about the expected format, like a choice of several predefined formats for your input.
Madhu's code is can workout, but some performance problem will arise because every failure case will raise the exception.
i think we need to find the reguler expression solution to find the pattern form the given date String.
you can find all most all reg expressions to date and time format in the following link
http://regexlib.com/DisplayPatterns.aspx?cattabindex=4&categoryId=5&AspxAutoDetectCookieSupport=1
Here is a generic solution the determine the pattern without knowing the date pattern in advance and without calling the parse method of SimpleDateFormat for all formats. You can get any date pattern from date string value by using the regex.
package com.utility.utils.modelmapper.datetime;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DateParser {
private static final Map<String, String> DATE_FORMAT_REGEXPS = new HashMap<String, String>() {
{
put("^\\d{8}$", "yyyyMMdd");
put("^\\d{12}$", "yyyyMMddHHmm");
put("^\\d{8}\\s\\d{4}$", "yyyyMMdd HHmm");
put("^\\d{14}$", "yyyyMMddHHmmss");
put("^\\d{8}\\s\\d{6}$", "yyyyMMdd HHmmss");
put("^\\d{1,2}-\\d{1,2}-\\d{4}$", "dd-MM-yyyy");
put("^\\d{4}-\\d{1,2}-\\d{1,2}$", "yyyy-MM-dd");
put("^\\d{1,2}/\\d{1,2}/\\d{4}$", "MM/dd/yyyy");
put("^\\d{4}/\\d{1,2}/\\d{1,2}$", "yyyy/MM/dd");
put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}$", "dd MMM yyyy");
put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}$", "dd MMMM yyyy");
put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}$", "dd-MM-yyyy HH:mm");
put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy-MM-dd HH:mm");
put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}$", "MM/dd/yyyy HH:mm");
put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy/MM/dd HH:mm");
put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMM yyyy HH:mm");
put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMMM yyyy HH:mm");
put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd-MM-yyyy HH:mm:ss");
put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy-MM-dd HH:mm:ss");
put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "MM/dd/yyyy HH:mm:ss");
put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy/MM/dd HH:mm:ss");
put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMM yyyy HH:mm:ss");
put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMMM yyyy HH:mm:ss");
put("^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{2}:\\d{2}\\.\\d{2}[-+]\\d{2}:\\d{2}$", "yyyy-MM-dd'T'HH:mm:ss.SSS");
}
};
/**
* To Determine the pattern by the string date value
*
* #param dateString
* #return The matching SimpleDateFormat pattern, or null if format is unknown.
*/
public static String determineDateFormat(String dateString) {
for (String regexp : DATE_FORMAT_REGEXPS.keySet()) {
if (dateString.matches(regexp) || dateString.toLowerCase().matches(regexp)) {
return DATE_FORMAT_REGEXPS.get(regexp);
}
}
return null;
}
public static void main(String[] args) {
parse("2011-09-27T07:04:21.97-05:00"); //here is your value
parse("20110917");
parse("01/02/2018");
parse("02-01-2018 06:07:59");
parse("02 January 2018");
}
public static void parse(String value) {
if (value != null) {
String format = determineDateFormat(value);
if (format != null) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
Date date = sdf.parse(value);
System.out.println(String.format("Format : %s | Value : %s | Parsed Date : %s", value, date, format));
} catch (ParseException e) {
// Failed the execution
}
}
}
}
}
Console output of the class:
Format : 2011-09-27T07:04:21.97-05:00 | Value : Tue Sep 27 07:04:21 LINT 2011 | Parsed Date : yyyy-MM-dd'T'HH:mm:ss.SSS
Format : 20110917 | Value : Sat Sep 17 00:00:00 LINT 2011 | Parsed Date : yyyyMMdd
Format : 01/02/2018 | Value : Tue Jan 02 00:00:00 LINT 2018 | Parsed Date : MM/dd/yyyy
Format : 02-01-2018 06:07:59 | Value : Tue Jan 02 06:07:59 LINT 2018 | Parsed Date : dd-MM-yyyy HH:mm:ss
Format : 02 January 2018 | Value : Tue Jan 02 00:00:00 LINT 2018 | Parsed Date : dd MMMM yyyy
Maybe I missed some of the date-time patterns here but for that the correct regex pattern should be added in the map.
You will need to take the inital date string and covert it to a date object and pass that converted date object and format it to your required string.
You could try dateparser.
It can recognize any String automatically, and parse it into Date, Calendar, LocalDateTime, OffsetDateTime correctly and quickly(1us~1.5us).
It doesn't based on any natural language analyzer or SimpleDateFormat or regex.Pattern.
With it, you don't have to prepare any appropriate patterns like yyyy-MM-dd'T'HH:mm:ss'Z' or MM/dd/yyyy HH:mm:ss etc:
Date date = DateParserUtils.parseDate("2015-04-29T10:15:00.500+0000");
Calendar calendar = DateParserUtils.parseCalendar("2015-04-29T10:15:00.500Z");
LocalDateTime dateTime = DateParserUtils.parseDateTime("2015-04-29 10:15:00.500 +00:00");
And it has better performance than loop-try multiple SimpleDateFormat.
Please enjoy it.
java.time and its predefined formatters
We cannot do this for just any date-time format. There are thousands of them, we cannot know them all (someone will invent a new one tomorrow), and some look alike so much we can’t tell which we’ve got.
I suggest that for the majority of purposes you need to parse the string, but you don’t need to know a format pattern for doing so. In very many cases, including the example from your question, 2011-09-27T07:04:21.97-05:00, we don’t need to specify a pattern (your string matches DateTimeFormatter.ISO_OFFSET_DATE_TIME).
Since Java 8 came out in 2014 (and even if still using Java 6 or 7), use java.time, the modern Java date and time API, for your date and time work.
I am defining an array of formatters for the formats we want to cater for. Please substitute your own set.
private static final DateTimeFormatter[] formatters = {
DateTimeFormatter.ISO_OFFSET_DATE_TIME,
DateTimeFormatter.RFC_1123_DATE_TIME,
new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter(),
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withLocale(Locale.US),
DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm")
.withZone(ZoneId.of("America/Los_Angeles"))
};
The following method tries the formatters in turn until one works:
private static OffsetDateTime parse(String dateTimeString) {
for (DateTimeFormatter formatter : formatters) {
try {
return ZonedDateTime.parse(dateTimeString, formatter)
.toOffsetDateTime();
} catch (DateTimeParseException dtpe) {
// Ignore, try next formatter
}
}
throw new IllegalArgumentException("String " + dateTimeString + " could not be parsed");
}
Let’s try it out with some different strings:
String[] dateTimeStrings = {
"2011-09-27T07:04:21.97-05:00",
"20110917",
"2012-07-04",
"12/27/2014 23:45",
"Mon, 12 Nov 2018 01:32:10 GMT",
"July 29, 2015 at 10:19:36 AM EDT",
};
for (String dts : dateTimeStrings) {
try {
System.out.format("%32s -> %s%n", dts, parse(dts));
} catch (IllegalArgumentException iae) {
System.out.format("%32s -> %s%n", dts, iae);
}
}
Output is:
2011-09-27T07:04:21.97-05:00 -> 2011-09-27T07:04:21.970-05:00
20110917 -> java.lang.IllegalArgumentException: String 20110917 could not be parsed
2012-07-04 -> 2012-07-04T00:00Z
12/27/2014 23:45 -> 2014-12-27T23:45-08:00
Mon, 12 Nov 2018 01:32:10 GMT -> 2018-11-12T01:32:10Z
July 29, 2015 at 10:19:36 AM EDT -> 2015-07-29T10:19:36-04:00
Other options
Techniques for parsing dates and times in multiple formats include:
Take a taste of the string to decide its format and use an appropriate formatter based on that. It’s best suited if you have just a few formats, though the answer by Vinit Solanki shows an elaborate version for quite many formats.
Use optional parts in a format pattern string. For example [uuuu][uu] will parse either four digit or two digit year (2021 or just 21).
Try several formatters in turn as shown in my code above. If you do need to know the pattern, use an array of patterns instead of an array of formatters.
Requiring the supplier of the string to supply a format patterns string too. This is not always as simple as it may sound, though.
Beware of ambiguity. The classical example is the two formats MM-dd-yyyy and dd-MM-yyyy. If we get a string of 03-09-2020, there’s no way to tell whether it means March 9 or 3rd September. Even worse, 02-05-07 might be yy-MM-dd, dd-MM-yy, MM-dd-yy and even more possibilities. As a consequence, make sure you don’t include two (or more) formatters that may parse the same string into different results.
Links
Oracle tutorial: Date Time explaining how to use java.time.
A fine answer by Arvind Kumar Avinash showing the use of optional parts in the format pattern string for parsing different formats.
HH:mm:ss.SSS => ([0-2]{1,}[0-9]{1,})(:)([0-5]{1,}[0-9]{1,})(:)([0-5]{1,}[0-9]{1,})(.)([0-9]{1,3})
yyyy-mm-dd => ([0-9]{4})(-)([0-1]{1,}[0-9]{1,})(-)([0-3]{1,}[0-9]{1,})

Categories

Resources