Formatting string to date in java
You can use a DateTimeFormatterBuilder
to create a DateTimeFormatter
that can parse days-of-month that have the "st", "nd", "rd" and "th" suffixes, and also lowercase AMPM.
// first create a map containing mapping the days of month to the suffixes
HashMap<Long, String> map = new HashMap<>();
for (long i = 1 ; i <= 31 ; i++) {
if (i == 1 || i == 21 || i == 31) {
map.put(i, i + "st");
} else if (i == 2 || i == 22){
map.put(i, i + "nd");
} else if (i == 3 || i == 23) {
map.put(i, i + "rd");
} else {
map.put(i, i + "th");
}
}
DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
.appendPattern("MMMM ")
.appendText(ChronoField.DAY_OF_MONTH, map) // here we use the map
.appendPattern(" yyyy HH:mm")
.appendText(ChronoField.AMPM_OF_DAY, Map.of(0L, "am", 1L, "pm")) // here we handle the lowercase AM PM
.toFormatter(Locale.US);
Usage:
LocalDateTime datetime = LocalDateTime.parse("April 5th 2021 12:30pm", dateFormatter);
How to format a non plain date in Java?
Replace all the expected undesired sufiixes by an empty string, and then parse:
String s = "10th Dec 2019";
SimpleDateFormat fmt = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH);
Date d = fmt.parse(s.replaceFirst("th|nd|st|rd", ""));
System.out.println("d = " + d);
How do you format the day of the month to say 11th, 21st or 23rd (ordinal indicator)?
// https://github.com/google/guava
import static com.google.common.base.Preconditions.*;
String getDayOfMonthSuffix(final int n) {
checkArgument(n >= 1 && n <= 31, "illegal day of month: " + n);
if (n >= 11 && n <= 13) {
return "th";
}
switch (n % 10) {
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
The table from @kaliatech is nice, but since the same information is repeated, it opens the chance for a bug. Such a bug actually exists in the table for 7tn
, 17tn
, and 27tn
(this bug might get fixed as time goes on because of the fluid nature of StackOverflow, so check the version history on the answer to see the error).
java.text.ParseException: Unparseable date: Augu 16, 1979
The problem is that replace("st", "")
also removes the st
ending of August
, resulting in the input string seen in the error message.
To handle this, you need to make sure the st
suffix is right after a digit, so it's part of the day value. You also need to handle all of 1st
, 2nd
, 3rd
, and 4th
.
This means that you should use regular expression, like this:
replaceFirst("(?<=\\d)(?:st|nd|rd|th)", "")
Test
public static void main(String[] args) throws Exception {
test("August 20th, 2012");
test("August 21st, 2012");
test("August 22nd, 2012");
test("August 23rd, 2012");
test("August 24th, 2012");
}
static void test(String input) throws ParseException {
String modified = input.replaceFirst("(?<=\\d)(?:st|nd|rd|th)", "");
DateFormat originalFormat = new SimpleDateFormat("MMMM dd, yyyy", Locale.ENGLISH);
DateFormat targetFormat = new SimpleDateFormat("yyyyMMdd");
Date date = originalFormat.parse(modified);
System.out.println(targetFormat.format(date));
}
Output
20120820
20120821
20120822
20120823
20120824
Related Topics
Inetaddress.Getlocalhost() Slow to Run (30+ Seconds)
In Java Lambda's Why Is Getclass() Called on a Captured Variable
Weird Java Behavior with Casts to Primitive Types
How to Use Google's Gson API to Deserialize JSON Properly
Display Blob (Image) Through Jsp
How to Determine If a String Has Non-Alphanumeric Characters
Why Does Java Allow Arrays of Size 0
How Read Doc or Docx File in Java
Making Spring-Data-Mongodb Multi-Tenant
Often Big Numbers Become Negative
How to Set Order of Repositories in Maven Settings.Xml
Maximum Size of a Method in Java
Why Functional Interfaces in Java 8 Have One Abstract Method
Differencebetween Synchronized on Lockobject and Using This as the Lock
Drawing a Component to Bufferedimage Causes Display Corruption
Why Catch Exceptions in Java, When You Can Catch Throwables