Java Date Parsing "a.m." and "p.m." - java

Using SimpleDateFormat, how can you parse the String: "2013-05-23T09:18:07 p.m..380+0000"
All my SimpleDateFormat Strings are tripping up on the "p.m." part.
Thanks in advance.
EDIT: We have no control over the format coming in.
I've tried:
"yyyy-MM-dd'T'HH:mm:ss a.a..SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaaa.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss a.'m'..SSSZ"
"yyyy-MM-dd'T'HH:mm:ss a.'m.'.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss a.'m..'SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aa'm'..SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aa'm.'.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaa'..'SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaa.'.'SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaa'.'.SSSZ"

It's not clear what the "380+0000" part is meant to be, but you can fix the AM/PM part, by setting the DateFormatSymbols for the SimpleDateFormat. Here's an example:
import java.util.*;
import java.text.*;
public class Test {
public static void main(String[] args) throws Exception {
String text = "2013-05-23T09:18:07 p.m..380+0000";
String pattern = "yyyy-MM-dd'T'hh:mm:ss aa'.380+0000'";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
DateFormatSymbols symbols = format.getDateFormatSymbols();
symbols = (DateFormatSymbols) symbols.clone();
symbols.setAmPmStrings(new String[] { "a.m.", "p.m."});
format.setDateFormatSymbols(symbols);
Date date = format.parse(text);
System.out.println(date);
}
}
I don't know whether you have to clone the DateFormatSymbols before mutating it - it's not clear, to be honest... the documentation points two ways:
DateFormatSymbols objects are cloneable. When you obtain a DateFormatSymbols object, feel free to modify the date-time formatting data. For instance, you can replace the localized date-time format pattern characters with the ones that you feel easy to remember. Or you can change the representative cities to your favorite ones.
Given that it's mentioning cloning, that suggests you should clone - but then the subsequent paragraph suggests not :(

Here's a implementation using Java 8's new java.time package, so you can ditch java.util.Date and java.text.SimpleDateFormat:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
String text = "2013-05-23T09:18:07 p.m..380+0000";
Map<Long, String> map = new HashMap<>();
map.put(0L, "a.m.");
map.put(1L, "p.m.");
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'hh:mm:ss ")
.appendText(ChronoField.AMPM_OF_DAY, map)
.appendPattern(".SSSZ").toFormatter();
OffsetDateTime dateTime = OffsetDateTime.parse(text, formatter);
System.out.println(dateTime);
}
}
Running it yields:
2013-05-23T21:18:07.380Z

Do it like this
String time="2013-05-23T09:18:07 p.m..380+0000";
int index1=time.indexOf("");
int index2 = time.indexOf(".."); // or you can give p.m. as argument if you want it to stop before pm
String result = time.substring(index1,index2);
System.out.print(result);
This has the following result
2013-05-23T09:18:07 p.m
I hope this helps

Just remove the p.m. part via string manipulation. It is redundant.
Than use a simple SimpleDateFormat to do the parsing.
Something along these lines:
String whatever = "2013-05-23T09:18:07 p.m..380+0000";
whatever = whatever.replaceAll(" p.m..", ":").replaceAll(" a.m..", ":");
System.out.println(whatever);
S
String pattern = "yyyy-MM-dd'T'hh:mm:ss:SSS'Z'";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
Date date;
try {
date = format.parse(whatever);
System.out.println(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Update
As pointed about by IAN, I missed out that the hours are not in 24hour format.
I did however get the millisecond part correct, and added the timezone part to Jon Skeet's answer to get:
String text = "2013-05-23T09:18:07 p.m..380+0000";
String pattern = "yyyy-MM-dd'T'hh:mm:ss aa'.'SSSZ";
SimpleDateFormat format = new SimpleDateFormat(pattern);
DateFormatSymbols symbols = format.getDateFormatSymbols();
symbols = (DateFormatSymbols) symbols.clone();
symbols.setAmPmStrings(new String[] { "a.m.", "p.m."});
format.setDateFormatSymbols(symbols);
Date date = format.parse(text);
System.out.println(date);

Related

How to compare dates using Spring Expression Language?

Can anyone give me any examples of how to compare Dates using Spring Expression Languange (Spel)?
I have searched far and wide and nothing I find seems to fit my purpose. I'm using Java 8 and I have a response Object with a ZonedDateTime field which I somehow need to compare to a string in the form of YYYY-MM-DD -- IE: is before, is after, is equal, etc.
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.systemDefault());
HashMap<String, Object> testHash = new HashMap<>();
testHash.put("dateField", zonedDateTime);
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariables(testHash);
Expression expression = parser.parseExpression("#dateField > '2016-01-01'");
The above is obviously not working. Anyone able to show me an example that does?
Below is the code for date comparison using Java 8 java.time package and Spring Expression Language. Hope this helps.
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import junit.framework.Assert;
public class TestDateSPEL {
#Test
public void testCompareDate() throws Exception {
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.systemDefault());
String otherDate = "2010-12-25 12:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneId.systemDefault());
ZonedDateTime zdtOtherDate = ZonedDateTime.parse(otherDate, formatter);
//SpEL Context
EvaluationContext context = new StandardEvaluationContext(new ZonedDateTimeUtil());
context.setVariable("dateOne", zonedDateTime);
context.setVariable("dateTwo", zdtOtherDate);
//SpEL Parser
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("compareDate(#dateOne, #dateTwo)");
int value = (Integer) exp.getValue(context);
//"zonedDateTime" is after "zdtOtherDate"
Assert.assertEquals(1, value);
}
}
class ZonedDateTimeUtil {
public int compareDate(ZonedDateTime dateOne, ZonedDateTime dateTwo){
return dateOne.compareTo(dateTwo);
}
}
I would recommend to parse your String to Instant or ZoneDateTime or any TemporalAccessor and then use method compareTo() of interface ChronoZonedDateTime that is extended by TemporalAccessor to compare two dates. See javadoc for compareTo(). Use class java.time.format.DateTimeFormatter to parse a String to TemporalAccessor. (method parse()). Your code may look like:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
TemporalAccessor ta = dtf.parse(yourDateString);
boolean result = yourZonedDateTime.compareTo(ta);
That's a base to start with. Also you can see this article that explains how to parse a String of unknown format into date. It might be helpful.
Java 8 java.time package: parsing any string to date
Please try this as example I hope that it will help you....
DateFormat destDf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDate;
Date endDate;
String strDate1="2016-08-09 00:00:00";
String strDate2="2015-11-19 00:00:00";
startDate = destDf.parse(strDate1);
endDate = destDf.parse(strDate2);
if(startDate.after(endDate)){
Object Date;
if(startDate.before(endDate))
if(startDate.equals(endDate))
//You can check date in java like this also
Date Date date = new Date();
if(date.getDate()==startDate.getDate() && date.getMonth()==startDate.getMonth() && date.getYear()==startDate.getYear()){
System.out.println("Date1 is equal Date2");
}

What is the easiest way to get the current date in YYYYMMDD format?

And how to print it as a string.
I tried this but I get the date in (YYYMMMMDDD HHSSMM) format:
System.out.println(LocalDateTime.now());
What is the easiest way to get the current date in (YYYYMMDD) format?
is that what you are looking for?
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
System.out.println(LocalDate.now().format(formatter));
This does the trick but may not be the easiest:
import java.util.*;
import java.text.*;
class Test {
public static void main (String[] args) {
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
System.out.println(dateFormat.format(date));
}
}
DateTimeFormatter.BASIC_ISO_DATE.format(LocalDate.now());
This is a very old question but gets me every time. There is a much simpler way now in one line:
String now = Instant.now().atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(now);
outputs: 2020-07-09
Just use: SimpleDateFormat
// Create an instance of SimpleDateFormat used for formatting
// the string representation of date (month/day/year)
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
// Get the date today using Calendar object.
Date today = Calendar.getInstance().getTime();
// Using DateFormat format method we can create a string
// representation of a date with the defined format.
String reportDate = df.format(today);
// Print what date is today!
System.out.println("Report Date: " + reportDate);
http://www.mkyong.com/java/how-to-convert-string-to-date-java/

What will be the date-time pattern in nl_NL locale of this?

In my project I am using a date conversion as follows (I have taken only the relevant chunk for brevity)
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class FormatTest {
public static void main(String[] args) {
try {
String destinationDateFormat = "MM/dd/yyyy HH:mm:ss";
String sourceDateFormat = "EEE MMM d HH:mm:ss z yyyy";
String dateString = "2011-12-20T00:00:00+00:00";
DatatypeFactory factory = DatatypeFactory.newInstance();
XMLGregorianCalendar cal = factory.newXMLGregorianCalendar(dateString);
Calendar gCal = cal.toGregorianCalendar();
Date convertedDate = gCal.getTime();
SimpleDateFormat sdf = new SimpleDateFormat(sourceDateFormat);
if (convertedDate != null) {
String convertedDateString = new SimpleDateFormat(destinationDateFormat).format(sdf.parse(
convertedDate.toString()).getTime());
System.out.println("Final Date :" + convertedDateString);
}
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
In my project the variables destinationDateFormat and sourceDateFormat is being read from a spring properties file. The above code works fine in the unix boxes where system locale is set as en_US or en_GB, but one of the test boxes has nl_NL locale and that's where the above code is failing giving a ParseException. The problem is like sourceDateFormat is not parse-able in nl_NL locale.
Can anybody suggest me what should be the corresponding sourceDateFormat in nl_NL locale?
I don't want to the change the java code as it is costly.
It looks like this might be it: EEEE, MMMM d, yyyy h:mm:ss a z
I wrote a small class to get it:
DateFormat f = getDateTimeInstance(FULL, FULL, new Locale("nl_NL"));
SimpleDateFormat sf = (SimpleDateFormat) f;
String p1 = sf.toPattern();
String p2 = sf.toLocalizedPattern();
System.out.println( p1 );
System.out.println( p2 );
Derived from this SO answer.
The date format symbols for en_US are:
GyMdkHmsSEDFwWahKzZ
The date format symbols for nl_NL are:
GyMdkHmsSEDFwWahKzZ
There is no difference. I got the date format symbols by executing the following Java lines:
System.out.println(DateFormatSymbols.getInstance
(new Locale("en_US")).getLocalPatternChars());
System.out.println(DateFormatSymbols.getInstance
(new Locale("nl_NL")).getLocalPatternChars());
I left the source date format the same:
String sourceDateFormat = "EEE MMM d HH:mm:ss z yyyy";
and modified your simple date format statement to this:
SimpleDateFormat sdf = new SimpleDateFormat(sourceDateFormat,
new Locale("nl_NL"));
With this simple date format change, your test code ran fine and produced the following results in the US Eastern time zone:
Date string: 2011-12-20T00:00:00+00:00
Final Date: 12/19/2011 19:00:00

How to remove some characters from a String

I am getting a date in this format:
2011-05-23 6:05:00
How can I obtain only 2011-05-23 from this string?
You could just take the index of the first space and use substring:
int firstSpace = text.indexOf(' ');
if (firstSpace != -1)
{
String truncated = text.substring(0, firstSpace);
// Use the truncated version
}
You'd need to work out what you wanted to do if there weren't any spaces.
However, if it's meant to be a valid date/time in a particular format and you know the format, I would parse it in that format, and then only use the date component. Joda Time makes it very easy to take just the date part - as well as being a generally better API.
EDIT: If you mean you've already got a Date object and you're trying to format it in a particular way, then SimpleDateFormat is your friend in the Java API - but again, I'd recommend using Joda Time and its DateTimeFormatter class:
DateTimeFormatter formatter = ISODateTimeFormat.date();
String text = formatter.print(date);
Using SimpleDateFormat:
parser = new SimpleDateFormat("yyyy-MM-dd k:m:s", locale);
Date date;
try {
date = (Date)parser.parse("2011-05-23 6:05:00");
} catch (ParseException e) {
}
formatter = new SimpleDateFormat("yyyy-MM-dd");
s = formatter.format(date);
Also:
http://www.exampledepot.com/egs/java.text/FormatDate.html
Standard way would be use of SimpleDateFormat
You can also accomplish it using String operation as follows
String result = str.substring(0,str.indexOf(" "));
You can use -
String arg="2011-05-23 6:05:00";
String str=arg.substring(0,arg.indexOf(" "));
Here you go:
import java.*;
import java.util.*;
import java.text.*;
public class StringApp {
public static void main(String[] args)
{
String oldDate = "2011-05-23 6:05:00";
String dateFormat = "yyyy-MM-dd";
try {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
Calendar cl = Calendar.getInstance();
cl.setTime(sdf.parse(oldDate));
String newDate = sdf.format(cl.getTime());
System.out.println(newDate);
}
catch (ParseException ex) {
}
}
}
Well an ineffective, but brute force method would be to say
String s = "2011-05-23 6:05:00";
String t = s.substring(0,s.length-7);
Or whatever the case should be
str = "2011-05-23 6:05:00"
str = str.substring(0,str.indexOf(" "));
Simplest way :
String str="2011-05-23 6:05:00";
str =str.subString(0,10);
Lots of answers, but no one had used regexp so far, so I just had to post an answer with regexp.
String date = "2011-05-23 6:05:00";
System.out.println(date.replaceFirst("\\s.*", ""));
Another answer which uses a regex.
String dateTime = "2011-05-23 6:05:00";
String date = dateTime.split(" ")[0];

How to parse dates in multiple formats using SimpleDateFormat

I am trying to parse some dates that are coming out of a document. It would appear users have entered these dates in a similar but not exact format.
here are the formats:
9/09
9/2009
09/2009
9/1/2009
9-1-2009
What is the best way to go about trying to parse all of these? These seem to be the most common, but I guess what is hanging me up is that if i have a pattern of "M/yyyy" wont that always catch before "MM/yyyy" Do I have to set up my try/catch blocks nested in a least restrictive to most restrictive way? it seems like it sure is going to take a lot of code duplication to get this right.
You'll need to use a different SimpleDateFormat object for each different pattern. That said, you don't need that many different ones, thanks to this:
Number: For formatting, the number of pattern letters is the minimum number of digits, and shorter numbers are zero-padded to this amount. For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.
So, you'll need these formats:
"M/y" (that covers 9/09, 9/2009, and 09/2009)
"M/d/y" (that covers 9/1/2009)
"M-d-y" (that covers 9-1-2009)
So, my advice would be to write a method that works something like this (untested):
// ...
List<String> formatStrings = Arrays.asList("M/y", "M/d/y", "M-d-y");
// ...
Date tryParse(String dateString)
{
for (String formatString : formatStrings)
{
try
{
return new SimpleDateFormat(formatString).parse(dateString);
}
catch (ParseException e) {}
}
return null;
}
What about just defining multiple patterns? They might come from a config file containing known patterns, hard coded it reads like:
List<SimpleDateFormat> knownPatterns = new ArrayList<SimpleDateFormat>();
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm.ss'Z'"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
for (SimpleDateFormat pattern : knownPatterns) {
try {
// Take a try
return new Date(pattern.parse(candidate).getTime());
} catch (ParseException pe) {
// Loop on
}
}
System.err.println("No known Date format found: " + candidate);
return null;
Matt's approach above is fine, but please be aware that you will run into problems if you use it to differentiate between dates of the format y/M/d and d/M/y. For instance, a formatter initialised with y/M/d will accept a date like 01/01/2009 and give you back a date which is clearly not what you wanted. I fixed the issue as follows, but I have limited time and I'm not happy with the solution for 2 main reasons:
It violates one of Josh Bloch's quidelines, specifically 'don't use exceptions to handle program flow'.
I can see the getDateFormat() method becoming a bit of a nightmare if you needed it to handle lots of other date formats.
If I had to make something that could handle lots and lots of different date formats and needed to be highly performant, then I think I would use the approach of creating an enum which linked each different date regex to its format. Then use MyEnum.values() to loop through the enum and test with if(myEnum.getPattern().matches(date)) rather than catching a dateformatexception.
Anway, that being said, the following can handle dates of the formats 'y/M/d' 'y-M-d' 'y M d' 'd/M/y' 'd-M-y' 'd M y' and all other variations of those which include time formats as well:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static final String[] timeFormats = {"HH:mm:ss","HH:mm"};
private static final String[] dateSeparators = {"/","-"," "};
private static final String DMY_FORMAT = "dd{sep}MM{sep}yyyy";
private static final String YMD_FORMAT = "yyyy{sep}MM{sep}dd";
private static final String ymd_template = "\\d{4}{sep}\\d{2}{sep}\\d{2}.*";
private static final String dmy_template = "\\d{2}{sep}\\d{2}{sep}\\d{4}.*";
public static Date stringToDate(String input){
Date date = null;
String dateFormat = getDateFormat(input);
if(dateFormat == null){
throw new IllegalArgumentException("Date is not in an accepted format " + input);
}
for(String sep : dateSeparators){
String actualDateFormat = patternForSeparator(dateFormat, sep);
//try first with the time
for(String time : timeFormats){
date = tryParse(input,actualDateFormat + " " + time);
if(date != null){
return date;
}
}
//didn't work, try without the time formats
date = tryParse(input,actualDateFormat);
if(date != null){
return date;
}
}
return date;
}
private static String getDateFormat(String date){
for(String sep : dateSeparators){
String ymdPattern = patternForSeparator(ymd_template, sep);
String dmyPattern = patternForSeparator(dmy_template, sep);
if(date.matches(ymdPattern)){
return YMD_FORMAT;
}
if(date.matches(dmyPattern)){
return DMY_FORMAT;
}
}
return null;
}
private static String patternForSeparator(String template, String sep){
return template.replace("{sep}", sep);
}
private static Date tryParse(String input, String pattern){
try{
return new SimpleDateFormat(pattern).parse(input);
}
catch (ParseException e) {}
return null;
}
}
If working in Java 1.8 you can leverage the DateTimeFormatterBuilder
public static boolean isTimeStampValid(String inputString)
{
DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofPattern("" + "[yyyy-MM-dd'T'HH:mm:ss.SSSZ]" + "[yyyy-MM-dd]"));
DateTimeFormatter dateTimeFormatter = dateTimeFormatterBuilder.toFormatter();
try {
dateTimeFormatter.parse(inputString);
return true;
} catch (DateTimeParseException e) {
return false;
}
}
See post: Java 8 Date equivalent to Joda's DateTimeFormatterBuilder with multiple parser formats?
In Apache commons lang, DateUtils class we have a method called parseDate. We can use this for parsing the date.
Also another library Joda-time also have the method to parse the date.
Here is the complete example (with main method) which can be added as a utility class in your project. All the format mentioned in SimpleDateFormate API is supported in the below method.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
public class DateUtility {
public static Date parseDate(String inputDate) {
Date outputDate = null;
String[] possibleDateFormats =
{
"yyyy.MM.dd G 'at' HH:mm:ss z",
"EEE, MMM d, ''yy",
"h:mm a",
"hh 'o''clock' a, zzzz",
"K:mm a, z",
"yyyyy.MMMMM.dd GGG hh:mm aaa",
"EEE, d MMM yyyy HH:mm:ss Z",
"yyMMddHHmmssZ",
"yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
"YYYY-'W'ww-u",
"EEE, dd MMM yyyy HH:mm:ss z",
"EEE, dd MMM yyyy HH:mm zzzz",
"yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm:ss.SSSzzzz",
"yyyy-MM-dd'T'HH:mm:sszzzz",
"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'HHmmss.SSSz",
"yyyy-MM-dd",
"yyyyMMdd",
"dd/MM/yy",
"dd/MM/yyyy"
};
try {
outputDate = DateUtils.parseDate(inputDate, possibleDateFormats);
System.out.println("inputDate ==> " + inputDate + ", outputDate ==> " + outputDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return outputDate;
}
public static String formatDate(Date date, String requiredDateFormat) {
SimpleDateFormat df = new SimpleDateFormat(requiredDateFormat);
String outputDateFormatted = df.format(date);
return outputDateFormatted;
}
public static void main(String[] args) {
DateUtility.parseDate("20181118");
DateUtility.parseDate("2018-11-18");
DateUtility.parseDate("18/11/18");
DateUtility.parseDate("18/11/2018");
DateUtility.parseDate("2018.11.18 AD at 12:08:56 PDT");
System.out.println("");
DateUtility.parseDate("Wed, Nov 18, '18");
DateUtility.parseDate("12:08 PM");
DateUtility.parseDate("12 o'clock PM, Pacific Daylight Time");
DateUtility.parseDate("0:08 PM, PDT");
DateUtility.parseDate("02018.Nov.18 AD 12:08 PM");
System.out.println("");
DateUtility.parseDate("Wed, 18 Nov 2018 12:08:56 -0700");
DateUtility.parseDate("181118120856-0700");
DateUtility.parseDate("2018-11-18T12:08:56.235-0700");
DateUtility.parseDate("2018-11-18T12:08:56.235-07:00");
DateUtility.parseDate("2018-W27-3");
}
}
Best and Simple Java 8 answer (from https://stackoverflow.com/a/59546290/2131040)
final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
This solution checks all the possible formats before throwing an exception. This solution is more convenient if you are trying to test for multiple date formats.
Date extractTimestampInput(String strDate){
final List<String> dateFormats = Arrays.asList("yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd");
for(String format: dateFormats){
SimpleDateFormat sdf = new SimpleDateFormat(format);
try{
return sdf.parse(strDate);
} catch (ParseException e) {
//intentionally empty
}
}
throw new IllegalArgumentException("Invalid input for date. Given '"+strDate+"', expecting format yyyy-MM-dd HH:mm:ss.SSS or yyyy-MM-dd.");
}
For the modern answer I am ignoring the requirement to use SimpleDateFormat. While using this class for parsing was a good idea in 2010 when this question was asked, it is now long outdated. The replacement, DateTimeFormatter, came out in 2014. The idea in the following is pretty much the same as in the accepted answer.
private static DateTimeFormatter[] parseFormatters = Stream.of("M/yy", "M/y", "M/d/y", "M-d-y")
.map(DateTimeFormatter::ofPattern)
.toArray(DateTimeFormatter[]::new);
public static YearMonth parseYearMonth(String input) {
for (DateTimeFormatter formatter : parseFormatters) {
try {
return YearMonth.parse(input, formatter);
} catch (DateTimeParseException dtpe) {
// ignore, try next format
}
}
throw new IllegalArgumentException("Could not parse " + input);
}
This parses each of the input strings from the question into a year-month of 2009-09. It’s important to try the two-digit year first since "M/y" could also parse 9/09, but into 0009-09 instead.
A limitation of the above code is it ignores the day-of-month from the strings that have one, like 9/1/2009. Maybe it’s OK as long as most formats have only month and year. To pick it up, we’d have to try LocalDate.parse() rather then YearMonth.parse() for the formats that include d in the pattern string. Surely it can be done.
I'm solved this problem more simple way using regex
fun parseTime(time: String?): Long {
val longRegex = "\\d{4}+-\\d{2}+-\\d{2}+\\w\\d{2}:\\d{2}:\\d{2}.\\d{3}[Z]\$"
val shortRegex = "\\d{4}+-\\d{2}+-\\d{2}+\\w\\d{2}:\\d{2}:\\d{2}Z\$"
val longDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssXXX")
val shortDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
return when {
Pattern.matches(longRegex, time) -> longDateFormat.parse(time).time
Pattern.matches(shortRegex, time) -> shortDateFormat.parse(time).time
else -> throw InvalidParamsException(INVALID_TIME_MESSAGE, null)
}
}
Implemented the same in scala, Please help urself with converting to Java, the core logic and functions used stays the same.
import java.text.SimpleDateFormat
import org.apache.commons.lang.time.DateUtils
object MultiDataFormat {
def main(args: Array[String]) {
val dates =Array("2015-10-31","26/12/2015","19-10-2016")
val possibleDateFormats:Array[String] = Array("yyyy-MM-dd","dd/MM/yyyy","dd-MM-yyyy")
val sdf = new SimpleDateFormat("yyyy-MM-dd") //change it as per the requirement
for (date<-dates) {
val outputDate = DateUtils.parseDateStrictly(date, possibleDateFormats)
System.out.println("inputDate ==> " + date + ", outputDate ==> " +outputDate + " " + sdf.format(outputDate) )
}
}
}
Using DateTimeFormatter it can be achieved as below:
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.TimeZone;
public class DateTimeFormatTest {
public static void main(String[] args) {
String pattern = "[yyyy-MM-dd[['T'][ ]HH:mm:ss[.SSSSSSSz][.SSS[XXX][X]]]]";
String timeSample = "2018-05-04T13:49:01.7047141Z";
SimpleDateFormat simpleDateFormatter = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
TemporalAccessor accessor = formatter.parse(timeSample);
ZonedDateTime zTime = LocalDateTime.from(accessor).atZone(ZoneOffset.UTC);
Date date=new Date(zTime.toEpochSecond()*1000);
simpleDateFormatter.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
System.out.println(simpleDateFormatter.format(date));
}
}
Pay attention at String pattern, this is the combination of multiple patterns. In open [ and close ] square brackets you can mention any kind of patterns.
I was having multiple date formats into json, and was extracting csv with universal format. I looked multiple places, tried different ways, but at the end I'm able to convert with the following simple code.
private String getDate(String anyDateFormattedString) {
#SuppressWarnings("deprecation")
Date date = new Date(anyDateFormattedString);
SimpleDateFormat dateFormat = new SimpleDateFormat(yourDesiredDateFormat);
String convertedDate = dateFormat.format(date);
return convertedDate;
}

Categories