Is there any java library available to parse language specific ordinal indicator/suffix?
I have a date value like the following: 26th May 2017
. I want to convert this to 26/05/2017
. Could anyone please guide me how to do?
Is there any java library available to parse language specific ordinal indicator/suffix?
I have a date value like the following: 26th May 2017
. I want to convert this to 26/05/2017
. Could anyone please guide me how to do?
You can parse this format directly to a Java 8 LocalDate
using a custom date format:
static final Map<Long, String> ORDINAL_DAYS = new HashMap<>();
static
{
ORDINAL_DAYS.put(1, "1st");
.... more ....
ORDINAL_DAYS.put(26, "26th");
.... more ....
ORDINAL_DAYS.put(31, "31st");
}
static final DateTimeFormatter FORMAT_DAY_MONTH_YEAR = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_MONTH, ORDINAL_DAYS)
.appendLiteral(' ')
.appendText(ChronoField.MONTH_OF_YEAR)
.appendLiteral(' ')
.appendText(ChronoField.YEAR)
.toFormatter();
String dateInString = "26th May 2017";
LocalDate date = LocalDate.parse(dateInString, FORMAT_DAY_MONTH_YEAR);
This is using the version of DateTimeFormatter.appendText
which accepts a map that is used to map the day string.
You will need to fill in all the missing entries in ORDINAL_DAYS
that I have left out for brevity.
static final DateTimeFormatter FORMAT_DAY_MONTH_YEAR = DateTimeFormatter.ofPattern("d['st']['nd']['rd']['th'] MMMM uuuu", Locale.ENGLISH);
. PS Consider specifying the locale. –
Amidst Assuming you don’t need very strict input validation, since you are converting from the format with th
on the number (or st
or nd
in 31st
, 2nd
and more), I suggest you simply remove those two letters first. A regex may do that:
// remove st, nd, rd or th after day of month
dateInString
= dateInString.replaceFirst("^(\\d+)(st|nd|rd|th)( \\w+ \\d+)$", "$1$3");
String dateOutString = LocalDate.parse(dateInString,
DateTimeFormatter.ofPattern("d MMM uuuu", Locale.ENGLISH))
.format(DateTimeFormatter.ofPattern("dd/MM/uuuu"));
The result is
26/05/2017
This works if your input contains a three letter abbreviation for the month, like Apr, May or Jun. To accept a full month name instead (April, May, June), you need 4 Ms instead of 3 in the format pattern: d MMMM uuuu
.
As stated by @OleV.V. in this comment, you can use a pattern with optional sections (to parse the different suffixes st, nd, rd and th).
You must also use a java.util.Locale
to force month names to English. The code will be like this:
String input = "26th May 2017";
DateTimeFormatter parser = DateTimeFormatter
// parse the day followed by st, nd, rd or th (using optional patterns delimited by [])
.ofPattern("dd['st']['nd']['rd']['th'] MMM yyyy")
// force English locale to parse month names
.withLocale(Locale.ENGLISH);
// formatter for dd/MM/yyyy output
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy").withLocale(Locale.ENGLISH);
System.out.println(formatter.format(parser.parse(input))); // 26/05/2017
The code above will work for month names with 3 letters (like May or Aug). If you want to parse the full names (like August or March), just change MMM
to MMMM
:
DateTimeFormatter parser = DateTimeFormatter
// using MMMM to parse full month name (like "August")
.ofPattern("dd['st']['nd']['rd']['th'] MMMM yyyy")
.withLocale(Locale.ENGLISH);
PS: If you want to parse both cases (3-letter or full month names) using the same parser
, you can do this:
DateTimeFormatter parser = DateTimeFormatter
// can parse "March" or "Mar" (MMMM or MMM)
.ofPattern("dd['st']['nd']['rd']['th'][ MMMM][ MMM] yyyy")
.withLocale(Locale.ENGLISH);
DateTimeFormatter.ofPattern()
for a bit terser code. –
Amidst ofPattern
- I usually don't need to set different locales. Thanks! –
Usually ofPattern()
. Even when you pass Locale.getDefault()
as the second argument, you are telling the reader (and yourself!) that you have thought about the locale and made a conscious decision about which locale to use. –
Amidst Assuming you are asking about Java, this link: https://www.mkyong.com/java/how-to-convert-string-to-date-java/ May help you.
The overall gist is:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDateExample3 {
public static void main(String[] argv) {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String dateInString = "26th May 2017"; // Remove your 'th', 'nd', etc. from the input string.
String withoutEnding = dateInString;
//Something like this
if(dateInString.contains("th") withoutEnding = dateInString.replace("th", "");
if(dateInString.contains("nd") withoutEnding = dateInString.replace("nd", "");
if(dateInString.contains("st") withoutEnding = dateInString.replace("st", "");
if(dateInString.contains("rd") withoutEnding = dateInString.replace("rd", "");
try {
Date date = formatter.parse(withoutEnding);
System.out.println(date);
System.out.println(formatter.format(date));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Where dd/MM/yyyy
is a date formatter that would give you
26/05/2017
.
Hope this helps!
EDIT: Also see http://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html for a full list of the different pattern letters for SimpleDateFormat
.
August
into Augu
. Unless of course it was already just Aug
from the start, this wasn’t very clear from the question. –
Amidst © 2022 - 2024 — McMap. All rights reserved.
st
,th
,rd
, andnd
. – Dimitrovo