How to Parse Dates with a Suffix "Th", "St" or "Nd" on the Day of the Month

How can I parse dates with a suffix th, st or nd on the day of the month?

There isn't anything inbuilt in .Net framework to parse dates in format of January 11th or February 22nd etc. You have to remove the suffix characters and then you can use DateTime.TryParseExact.

For dates with Suffix st, th, you can use string.Replace to remove that part and then use DateTime.TryParseExact. Like.

string str = "1st February 2013";
DateTime dtObject;
string replacedStr = str.Substring(0,4)
.Replace("nd","")
.Replace("th","")
.Replace("rd","")
.Replace("st","")
+ str.Substring(4);

if (DateTime.TryParseExact(replacedStr,
"dd MMMMM yyyy",
CultureInfo.InstalledUICulture,
DateTimeStyles.None,
out dtObject))
{
//valid date
}

For multiple formats, you can specify the formats in a string array and later you can use that. It returns a bool value indicating if the parsing was successful or not.

Example from MSDN:

string[] formats= {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
"MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss",
"M/d/yyyy hh:mm tt", "M/d/yyyy hh tt",
"M/d/yyyy h:mm", "M/d/yyyy h:mm",
"MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"};
string[] dateStrings = {"5/1/2009 6:32 PM", "05/01/2009 6:32:05 PM",
"5/1/2009 6:32:00", "05/01/2009 06:32",
"05/01/2009 06:32:00 PM", "05/01/2009 06:32:00"};
DateTime dateValue;

foreach (string dateString in dateStrings)
{
if (DateTime.TryParseExact(dateString, formats,
new CultureInfo("en-US"),
DateTimeStyles.None,
out dateValue))
Console.WriteLine("Converted '{0}' to {1}.", dateString, dateValue);
else
Console.WriteLine("Unable to convert '{0}' to a date.", dateString);

Parsing a date’s ordinal indicator ( st, nd, rd, th ) in a date-time string

Java's SimpleDateFormat doesn't support an ordinal suffix, but the ordinal suffix is just eye candy - it is redundant and can easily be removed to allow a straightforward parse:

Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
.parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));

The replace regex is so simple because those sequences won't appear anywhere else in a valid date.


To handle any language that appends any length of ordinal indicator characters from any language as a suffix:

Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
.parse(str.replaceAll("(?<=\\d)(?=\\D* \\d+ )\\p{L}+", ""));

Some languages, eg Mandarin, prepend their ordinal indicator, but that could be handled too using an alternation - left as an exercise for the reader :)

Format for ordinal dates (day of month with suffixes -st, -nd, -rd, -th)

Enjoy the power of lubridate:

library(lubridate)    
mdy(ord_dates)

[1] "2016-09-01" "2016-09-02" "2016-09-03" "2016-09-04"

Internally, lubridate doesn't have any special conversion specifications which enable this. Rather, lubridate first uses (by smart guessing) the format "%B %dst, %Y". This gets the first element of ord_dates.

It then checks for NAs and repeats its smart guessing on the remaining elements, settling on "%B %dnd, %Y" to get the second element. It continues in this way until there are no NAs left (which happens in this case after 4 iterations), or until its smart guessing fails to turn up a likely format candidate.

You can imagine this makes lubridate slower, and it does -- about half the speed of just using the smart regex suggested by @alistaire above:

set.seed(109123)
ord_dates <- sample(
c("September 1st, 2016", "September 2nd, 2016",
"September 3rd, 2016", "September 4th, 2016"),
1e6, TRUE
)

library(microbenchmark)

microbenchmark(times = 10L,
lubridate = mdy(ord_dates),
base = as.Date(sub("\\D+,", "", ord_dates),
format = "%B %e %Y"))
# Unit: seconds
# expr min lq mean median uq max neval cld
# lubridate 2.167957 2.219463 2.290950 2.252565 2.301725 2.587724 10 b
# base 1.183970 1.224824 1.218642 1.227034 1.228324 1.229095 10 a

The obvious advantage in lubridate's favor being its conciseness and flexibility.

How to parse date days that contain st, nd, rd, or th?

You can use regex to replace st, nd, rd, th with an empty string:

import re
def solve(s):
return re.sub(r'(\d)(st|nd|rd|th)', r'\1', s)

Demo:

>>> datetime.strptime(solve('1st January 2014'), "%d %B %Y")
datetime.datetime(2014, 1, 1, 0, 0)
>>> datetime.strptime(solve('3rd March 2014'), "%d %B %Y")
datetime.datetime(2014, 3, 3, 0, 0)
>>> datetime.strptime(solve('2nd June 2014'), "%d %B %Y")
datetime.datetime(2014, 6, 2, 0, 0)
>>> datetime.strptime(solve('1st August 2014'), "%d %B %Y")
datetime.datetime(2014, 8, 1, 0, 0)

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).

python format datetime with st, nd, rd, th (english ordinal suffix) like PHP's S

The django.utils.dateformat has a function format that takes two arguments, the first one being the date (a datetime.date [[or datetime.datetime]] instance, where datetime is the module in Python's standard library), the second one being the format string, and returns the resulting formatted string. The uppercase-S format item (if part of the format string, of course) is the one that expands to the proper one of 'st', 'nd', 'rd' or 'th', depending on the day-of-month of the date in question.

How do you format the day of the month to say “11th”, “21st” or “23rd” in Dart?

Try out this package, Jiffy, inspired by momentjs.

Just simply add the do date pattern. See below

Jiffy([2014, 4, 23]).format("EEEE MMMM do, yyyy"); // Wednesday April 23rd, 2014

You can also add your DateTime object

Jiffy(DateTime(2014, 4, 23)).format("EEEE MMMM do, yyyy"); // Wednesday April 23rd, 2014

Getting day suffix when using DateTime.ToString()

As a reference I always use/refer to [SteveX String Formatting] 1
and there doesn't appear to be any "th" in any of the available variables but you could easily build a string with

string.Format("{0:dddd dd}{1} {0:MMMM yyyy}", DateTime.Now, (?));

You would then have to supply a "st" for 1, "nd" for 2, "rd" for 3, and "th" for all others and could be in-lined with a "? :" statement.

var now = DateTime.Now;
(now.Day % 10 == 1 && now.Day % 100 != 11) ? "st"
: (now.Day % 10 == 2 && now.Day % 100 != 12) ? "nd"
: (now.Day % 10 == 3 && now.Day % 100 != 13) ? "rd"
: "th"


Related Topics



Leave a reply



Submit