Ken*_*ume 131 java date ordinal simpledateformat
我知道这会给我这个月的一天,一个数(11
,21
,23
):
SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d");
Run Code Online (Sandbox Code Playgroud)
但是,如何格式化月份中的日期以包含序数指标,比方说11th
,21st
或者23rd
?
Gre*_*tes 167
// 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";
}
}
Run Code Online (Sandbox Code Playgroud)
来自@kaliatech的表很不错,但由于重复了相同的信息,因此它为错误提供了机会.这个bug实际上存在于表中7tn
,17tn
和,27tn
(由于StackOverflow的流畅特性,这个bug可能会随着时间的推移而得到修复,因此请查看答案的版本历史记录以查看错误).
kal*_*ech 48
JDK中没有任何内容可以做到这一点.
static String[] suffixes =
// 0 1 2 3 4 5 6 7 8 9
{ "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th",
// 10 11 12 13 14 15 16 17 18 19
"th", "th", "th", "th", "th", "th", "th", "th", "th", "th",
// 20 21 22 23 24 25 26 27 28 29
"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th",
// 30 31
"th", "st" };
Date date = new Date();
SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d");
int day = Integer.parseInt(formatDateOfMonth.format(date));
String dayStr = day + suffixes[day];
Run Code Online (Sandbox Code Playgroud)
或使用日历:
Calendar c = Calendar.getInstance();
c.setTime(date);
int day = c.get(Calendar.DAY_OF_MONTH);
String dayStr = day + suffixes[day];
Run Code Online (Sandbox Code Playgroud)
根据@thorbjørn-ravn-andersen的评论,这样的表在本地化时可能会有所帮助:
static String[] suffixes =
{ "0th", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th",
"10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th",
"20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th",
"30th", "31st" };
Run Code Online (Sandbox Code Playgroud)
小智 34
private String getCurrentDateInSpecificFormat(Calendar currentCalDate) {
String dayNumberSuffix = getDayNumberSuffix(currentCalDate.get(Calendar.DAY_OF_MONTH));
DateFormat dateFormat = new SimpleDateFormat(" d'" + dayNumberSuffix + "' MMMM yyyy");
return dateFormat.format(currentCalDate.getTime());
}
private String getDayNumberSuffix(int day) {
if (day >= 11 && day <= 13) {
return "th";
}
switch (day % 10) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
Run Code Online (Sandbox Code Playgroud)
oco*_*odo 14
String ordinal(int num)
{
String[] suffix = {"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"};
int m = num % 100;
return String.valueOf(num) + suffix[(m > 3 && m < 21) ? 0 : (m % 10)];
}
Run Code Online (Sandbox Code Playgroud)
Sar*_*arz 14
问题有点旧.因为这个问题非常嘈杂所以发布我用静态方法作为util解决了.只需复制,粘贴和使用它!
public static String getFormattedDate(Date date){
Calendar cal=Calendar.getInstance();
cal.setTime(date);
//2nd of march 2015
int day=cal.get(Calendar.DATE);
if(!((day>10) && (day<19)))
switch (day % 10) {
case 1:
return new SimpleDateFormat("d'st' 'of' MMMM yyyy").format(date);
case 2:
return new SimpleDateFormat("d'nd' 'of' MMMM yyyy").format(date);
case 3:
return new SimpleDateFormat("d'rd' 'of' MMMM yyyy").format(date);
default:
return new SimpleDateFormat("d'th' 'of' MMMM yyyy").format(date);
}
return new SimpleDateFormat("d'th' 'of' MMMM yyyy").format(date);
}
Run Code Online (Sandbox Code Playgroud)
用于测试purose
示例:从main方法调用它!
Date date = new Date();
Calendar cal=Calendar.getInstance();
cal.setTime(date);
for(int i=0;i<32;i++){
System.out.println(getFormattedDate(cal.getTime()));
cal.set(Calendar.DATE,(cal.getTime().getDate()+1));
}
Run Code Online (Sandbox Code Playgroud)
输出:
22nd of February 2018
23rd of February 2018
24th of February 2018
25th of February 2018
26th of February 2018
27th of February 2018
28th of February 2018
1st of March 2018
2nd of March 2018
3rd of March 2018
4th of March 2018
5th of March 2018
6th of March 2018
7th of March 2018
8th of March 2018
9th of March 2018
10th of March 2018
11th of March 2018
12th of March 2018
13th of March 2018
14th of March 2018
15th of March 2018
16th of March 2018
17th of March 2018
18th of March 2018
19th of March 2018
20th of March 2018
21st of March 2018
22nd of March 2018
23rd of March 2018
24th of March 2018
25th of March 2018
Run Code Online (Sandbox Code Playgroud)
Ole*_*.V. 10
我想提出现代的答案.SimpleDateFormat
8年前问这个问题时,这个课程可以使用,但你现在应该避免使用它,因为它不仅已经过时了,而且还非常麻烦.请java.time
改用.
编辑
DateTimeFormatterBuilder.appendText(TemporalField, Map<Long, String>)
非常适合这个目的.使用它我们构建了一个为我们工作的格式化程序:
Map<Long, String> ordinalNumbers = new HashMap<>(42);
ordinalNumbers.put(1L, "1st");
ordinalNumbers.put(2L, "2nd");
ordinalNumbers.put(3L, "3rd");
ordinalNumbers.put(21L, "21st");
ordinalNumbers.put(22L, "22nd");
ordinalNumbers.put(23L, "23rd");
ordinalNumbers.put(31L, "31st");
for (long d = 1; d <= 31; d++) {
ordinalNumbers.putIfAbsent(d, "" + d + "th");
}
DateTimeFormatter dayOfMonthFormatter = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_MONTH, ordinalNumbers)
.appendPattern(" MMMM")
.toFormatter();
LocalDate date = LocalDate.of(2018, Month.AUGUST, 30);
for (int i = 0; i < 6; i++) {
System.out.println(date.format(dayOfMonthFormatter));
date = date.plusDays(1);
}
Run Code Online (Sandbox Code Playgroud)
此代码段的输出是:
Run Code Online (Sandbox Code Playgroud)30th August 31st August 1st September 2nd September 3rd September 4th September
老答案
这段代码较短,但恕我直言并不那么优雅.
// ordinal indicators by numbers (1-based, cell 0 is wasted)
String[] ordinalIndicators = new String[31 + 1];
Arrays.fill(ordinalIndicators, 1, ordinalIndicators.length, "th");
ordinalIndicators[1] = ordinalIndicators[21] = ordinalIndicators[31] = "st";
ordinalIndicators[2] = ordinalIndicators[22] = "nd";
ordinalIndicators[3] = ordinalIndicators[23] = "rd";
DateTimeFormatter dayOfMonthFormatter = DateTimeFormatter.ofPattern("d");
LocalDate today = LocalDate.now(ZoneId.of("America/Menominee")).plusWeeks(1);
System.out.println(today.format(dayOfMonthFormatter)
+ ordinalIndicators[today.getDayOfMonth()]);
Run Code Online (Sandbox Code Playgroud)
我刚刚运行这个片段
第23
其中一个特点java.time
是,将月份的日期作为一个简单而可靠int
,显然需要从表中选择正确的后缀.
我建议你也写一个单元测试.
PS类似的格式,也可用于分析含像序号日期字符串1st
,2nd
等等.这是在做了这样一个问题:爪哇-解析日期可选秒.
链接: Oracle教程:日期时间解释如何使用java.time
.
如果您试图了解i18n,解决方案会变得更加复杂.
问题在于,在其他语言中,后缀不仅可能取决于数字本身,还取决于其所依据的名词.例如在俄语中它将是"2-ййдень",但是"2-яянеделя"(这些意思是"第二天",但是"第二周").如果我们只格式化几天,这不适用,但在更通用的情况下,您应该注意复杂性.
我认为很好的解决方案(我没有时间实际实现)将扩展SimpleDateFormetter以在传递给父类之前应用Locale感知的MessageFormat.通过这种方式,您可以支持三月格式%M获得"3-rd",%MM获得"03-rd",%MMM获得"第三".从外部看,这个类看起来像常规的SimpleDateFormatter,但支持更多格式.此外,如果常规SimpleDateFormetter错误地应用此模式,则结果将被错误地格式化,但仍然可读.
这里的许多示例不适用于 11、12、13。这是更通用的,适用于所有情况。
switch (date) {
case 1:
case 21:
case 31:
return "" + date + "st";
case 2:
case 22:
return "" + date + "nd";
case 3:
case 23:
return "" + date + "rd";
default:
return "" + date + "th";
}
Run Code Online (Sandbox Code Playgroud)
使用新的java.time包和更新的 Java switch 语句,以下代码可以轻松地将序数放置在一个月中的某一天。一个缺点是这不适合DateFormatter类中指定的固定格式。
只需创建某种格式的一天,但包括%s%s
稍后添加日期和序号。
ZonedDateTime ldt = ZonedDateTime.now();
String format = ldt.format(DateTimeFormatter
.ofPattern("EEEE, MMMM '%s%s,' yyyy hh:mm:ss a zzz"));
Run Code Online (Sandbox Code Playgroud)
现在将星期几和刚刚格式化的日期传递给辅助方法以添加序数日。
int day = ldt.getDayOfMonth();
System.out.println(applyOrdinalDaySuffix(format, day));
Run Code Online (Sandbox Code Playgroud)
印刷
Tuesday, October 6th, 2020 11:38:23 AM EDT
Run Code Online (Sandbox Code Playgroud)
这是辅助方法。
使用Java 14
switch 表达式可以非常轻松地获取序数。
public static String applyOrdinalDaySuffix(String format,
int day) {
if (day < 1 || day > 31)
throw new IllegalArgumentException(
String.format("Bad day of month (%s)", day));
String ord = switch (day) {
case 1, 21, 31 -> "st";
case 2, 22 -> "nd";
case 3, 23 -> "rd";
default -> "th";
};
return String.format(format, day, ord);
}
Run Code Online (Sandbox Code Playgroud)
RuleBasedNumberFormat
在 ICU 图书馆我很欣赏 @Pierre-Olivier Dybman 提供的 ICU 项目库的链接(http://www.icu-project.org/apiref/icu4j/com/ibm/icu/text/RuleBasedNumberFormat.html),但是仍然需要弄清楚了解如何使用它,因此RuleBasedNumberFormat
下面是一个用法示例。
它只会格式化单个数字而不是整个日期,因此如果查找格式为“2 月 3 日星期一”的日期,您将需要构建一个组合字符串。
以下代码将 设为RuleBasedNumberFormat
给定区域设置的序数格式,创建java.time ZonedDateTime
,然后将数字及其序数格式化为字符串。
RuleBasedNumberFormat numOrdinalFormat = new RuleBasedNumberFormat(Locale.UK,
RuleBasedNumberFormat.ORDINAL);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Pacific/Auckland"));
String dayNumAndOrdinal = numOrdinalFormat.format(zdt.toLocalDate().getDayOfMonth());
Run Code Online (Sandbox Code Playgroud)
输出示例:
第三名
或者
第四名
ETC。