Java 您如何将一个月中的某一天格式化为“日”;第十一条&引用;“21世纪”;或;第二十三条;(顺序指示符)?
我知道这会给我一个数字(Java 您如何将一个月中的某一天格式化为“日”;第十一条&引用;“21世纪”;或;第二十三条;(顺序指示符)?,java,date,simpledateformat,ordinal,Java,Date,Simpledateformat,Ordinal,我知道这会给我一个数字(11,21,23): 但是如何设置一个月中的哪一天的格式以包括,比如说第11天、第21天或第23天 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
11
,21
,23
):
但是如何设置一个月中的哪一天的格式以包括,比如说第11天、第21天或第23天
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];
或使用日历:
Calendar c = Calendar.getInstance();
c.setTime(date);
int day = c.get(Calendar.DAY_OF_MONTH);
String dayStr = day + suffixes[day];
根据@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" };
//https://github.com/google/guava
导入静态com.google.common.base.Premissions.*;
字符串getDayOfMonthSuffix(最终整数n){
checkArgument(n>=1&&n=11&&n字符串序号(int num)
{
字符串[]后缀={“th”、“st”、“nd”、“rd”、“th”、“th”、“th”、“th”、“th”、“th”、“th”、“th”};
int m=num%100;
返回字符串.valueOf(num)+后缀[(m>3&&m<21)?0:(m%10)];
}
有一种更简单、更可靠的方法。您需要使用的函数是getDateFromDateString(dateString);它基本上删除日期字符串的st/nd/rd/th并对其进行简单解析。您可以将SimpleDateFormat更改为任何格式,这将起作用
public static final SimpleDateFormat sdf = new SimpleDateFormat("d");
public static final Pattern p = Pattern.compile("([0-9]+)(st|nd|rd|th)");
private static Date getDateFromDateString(String dateString) throws ParseException {
return sdf.parse(deleteOrdinal(dateString));
}
private static String deleteOrdinal(String dateString) {
Matcher m = p.matcher(dateString);
while (m.find()) {
dateString = dateString.replaceAll(Matcher.quoteReplacement(m.group(0)), m.group(1));
}
return dateString;
}私有字符串getCurrentDateInSpecificFormat(日历currentCalDate){
字符串dayNumberSuffix=getDayNumberSuffix(currentCalDate.get(Calendar.DAY/u/u MONTH));
DateFormat DateFormat=新的SimpleDateFormat(“d'”+dayNumberSuffix+“'MMMM yyyy”);
return dateFormat.format(currentCalDate.getTime());
}
私有字符串getDayNumberSuffix(整数天){
如果(day>=11&&day,Greg提供的解决方案的唯一问题是,它不考虑以“青少年”数字结尾的大于100的数字。例如,111应该是第111位,而不是第111位。这是我的解决方案:
/**
* Return ordinal suffix (e.g. 'st', 'nd', 'rd', or 'th') for a given number
*
* @param value
* a number
* @return Ordinal suffix for the given number
*/
public static String getOrdinalSuffix( int value )
{
int hunRem = value % 100;
int tenRem = value % 10;
if ( hunRem - tenRem == 10 )
{
return "th";
}
switch ( tenRem )
{
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
以下是一个更有效的问题答案,而不是硬编码的风格
要将日期更改为序号,您需要使用以下命令
找到我完整的问题答案。如果你试图了解i18n,解决方案会变得更加复杂
问题是,在其他语言中,后缀可能不仅取决于数字本身,还取决于它所计算的名词。例如,在俄语中,后缀可能是“2-ааааааааааааааааа107。如果我们只在几天内设置格式,则这不适用,但在更一般的情况下,您应该注意复杂性
我认为很好的解决方案(我没有时间实际实现)是在传递给父类之前扩展SimpleDateFormatter以应用区域设置感知MessageFormat。这样,您就可以支持三月格式%M获得“3-rd”、%MM获得“03-rd”和%MMM获得“第三”。从外部看,该类类似于常规SimpleDataFormatter,但支持更多格式。此外,如果常规SimpleDataFormatter错误地应用了此模式,则结果的格式可能不正确,但仍然可读。这里的许多示例不适用于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";
}
以下方法可用于获取传递给它的日期的格式化字符串。它将使用Java中的SimpleDataFormat将日期格式化为1、2、3、4..。例如:-2015年9月1日
public String getFormattedDate(Date date){
Calendar cal=Calendar.getInstance();
cal.setTime(date);
//2nd of march 2015
int day=cal.get(Calendar.DATE);
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);
}
这个问题有点老了。因为这个问题很吵,所以把我用静态方法解决的问题作为一个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);
}
我不能满足于那些要求基于手动格式的纯英语解决方案的答案。我一直在寻找一个合适的解决方案,现在我终于找到了
你应该使用。它工作得很好,而且尊重当地环境。在科特林,你可以这样使用
fun changeDateFormats(currentFormat: String, dateString: String): String {
var result = ""
try {
val formatterOld = SimpleDateFormat(currentFormat, Locale.getDefault())
formatterOld.timeZone = TimeZone.getTimeZone("UTC")
var date: Date? = null
date = formatterOld.parse(dateString)
val dayFormate = SimpleDateFormat("d", Locale.getDefault())
var day = dayFormate.format(date)
val formatterNew = SimpleDateFormat("hh:mm a, d'" + getDayOfMonthSuffix(day.toInt()) + "' MMM yy", Locale.getDefault())
if (date != null) {
result = formatterNew.format(date)
}
} catch (e: ParseException) {
e.printStackTrace()
return dateString
}
return result
}
private fun getDayOfMonthSuffix(n: Int): String {
if (n in 11..13) {
return "th"
}
when (n % 10) {
1 -> return "st"
2 -> return "nd"
3 -> return "rd"
else -> return "th"
}
}
txt_chat_time_me.text = changeDateFormats("SERVER_DATE", "DATE")
像这样
fun changeDateFormats(currentFormat: String, dateString: String): String {
var result = ""
try {
val formatterOld = SimpleDateFormat(currentFormat, Locale.getDefault())
formatterOld.timeZone = TimeZone.getTimeZone("UTC")
var date: Date? = null
date = formatterOld.parse(dateString)
val dayFormate = SimpleDateFormat("d", Locale.getDefault())
var day = dayFormate.format(date)
val formatterNew = SimpleDateFormat("hh:mm a, d'" + getDayOfMonthSuffix(day.toInt()) + "' MMM yy", Locale.getDefault())
if (date != null) {
result = formatterNew.format(date)
}
} catch (e: ParseException) {
e.printStackTrace()
return dateString
}
return result
}
private fun getDayOfMonthSuffix(n: Int): String {
if (n in 11..13) {
return "th"
}
when (n % 10) {
1 -> return "st"
2 -> return "nd"
3 -> return "rd"
else -> return "th"
}
}
txt_chat_time_me.text = changeDateFormats("SERVER_DATE", "DATE")
我想提供一个现代的答案。SimpleDateFormat
类在8年前被问到这个问题时可以使用,但现在应该避免使用它,因为它不仅过时很久,而且非常麻烦。请改用java.time
编辑
DateTimeFormatterBuilder.appendText(TemporalField,Map)
非常适合此用途。使用它,我们可以构建一个格式化程序,为我们完成以下工作:
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);
}
旧答案
此代码较短,但不太优雅
// 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()]);
刚才运行这个代码片段我得到了
23
java.time
的许多特性之一是,将月份的日期作为int
获取是简单可靠的,这显然是从表中选择正确后缀所必需的
我建议您也编写一个单元测试
PS类似的格式化程序也可用于解析包含序号的日期字符串,如在中完成的1st
、2nd
等
链接:解释如何使用java.time
这里有一种方法,如果找到模式d'00'
,则使用正确的后缀文字更新DateTimeFormatter模式,例如,对于月1日,它将被替换为d'st'
。一旦模式被更新,它就可以直接输入到DateTimeFormatter将执行其余操作
private static String[] suffixes = {"th", "st", "nd", "rd"};
private static String updatePatternWithDayOfMonthSuffix(TemporalAccessor temporal, String pattern) {
String newPattern = pattern;
// Check for pattern `d'00'`.
if (pattern.matches(".*[d]'00'.*")) {
int dayOfMonth = temporal.get(ChronoField.DAY_OF_MONTH);
int relevantDigits = dayOfMonth < 30 ? dayOfMonth % 20 : dayOfMonth % 30;
String suffix = suffixes[relevantDigits <= 3 ? relevantDigits : 0];
newPattern = pattern.replaceAll("[d]'00'", "d'" + suffix + "'");
}
return newPattern;
}
因此,如果格式化模式是在Java代码之外定义的,例如,模板,如果您可以在Java中定义模式,那么@OleV.V.的答案可能更合适我编写了我的self a helper方法来获取这方面的模式
public static String getPattern(int month) {
String first = "MMMM dd";
String last = ", yyyy";
String pos = (month == 1 || month == 21 || month == 31) ? "'st'" : (month == 2 || month == 22) ? "'nd'" : (month == 3 || month == 23) ? "'rd'" : "'th'";
return first + pos + last;
}
然后我们可以称之为
LocalDate localDate = LocalDate.now();//For reference
int month = localDate.getDayOfMonth();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(getPattern(month));
String date = localDate.format(formatter);
System.out.println(date);
输出是
December 12th, 2018
ICU库中基于规则的数字格式
我很欣赏从@Pierre Olivier Dybman()链接到ICU项目库的链接,但是我仍然需要弄清楚如何使用它,下面是一个使用RuleBasedNumberFormat
的示例
它将只格式化单个数字,而不是整个日期,因此,如果在表单中查找日期,则需要构建一个组合字符串
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);
}
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()]);
private static String[] suffixes = {"th", "st", "nd", "rd"};
private static String updatePatternWithDayOfMonthSuffix(TemporalAccessor temporal, String pattern) {
String newPattern = pattern;
// Check for pattern `d'00'`.
if (pattern.matches(".*[d]'00'.*")) {
int dayOfMonth = temporal.get(ChronoField.DAY_OF_MONTH);
int relevantDigits = dayOfMonth < 30 ? dayOfMonth % 20 : dayOfMonth % 30;
String suffix = suffixes[relevantDigits <= 3 ? relevantDigits : 0];
newPattern = pattern.replaceAll("[d]'00'", "d'" + suffix + "'");
}
return newPattern;
}
public static String format(TemporalAccessor temporal, String pattern) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(updatePatternWithDayOfMonthSuffix(temporal, pattern));
return formatter.format(temporal);
}
public static String getPattern(int month) {
String first = "MMMM dd";
String last = ", yyyy";
String pos = (month == 1 || month == 21 || month == 31) ? "'st'" : (month == 2 || month == 22) ? "'nd'" : (month == 3 || month == 23) ? "'rd'" : "'th'";
return first + pos + last;
}
LocalDate localDate = LocalDate.now();//For reference
int month = localDate.getDayOfMonth();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(getPattern(month));
String date = localDate.format(formatter);
System.out.println(date);
December 12th, 2018
RuleBasedNumberFormat numOrdinalFormat = new RuleBasedNumberFormat(Locale.UK,
RuleBasedNumberFormat.ORDINAL);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Pacific/Auckland"));
String dayNumAndOrdinal = numOrdinalFormat.format(zdt.toLocalDate().getDayOfMonth());
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);
}
ZonedDateTime ldt = ZonedDateTime.now();
String format = ldt.format(DateTimeFormatter
.ofPattern("EEEE, MMMM '%s%s,' yyyy hh:mm:ss a zzz"));
int day = ldt.getDayOfMonth();
System.out.println(applyOrdinalDaySuffix(format, day));
Tuesday, October 6th, 2020 11:38:23 AM EDT
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);
}
fun Int.ordinalAbbrev() =
if (this % 100 / 10 == 1) "th"
else when (this % 10) { 1 -> "st" 2 -> "nd" 3 -> "rd" else -> "th" }
fun getFormatedDate(date: String): String {
date.let {
try {
val parser = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val formatter = SimpleDateFormat("dd MMMM", Locale.getDefault())
val dateArray = formatter.format(parser.parse(it)).split(" ").toTypedArray()
val formatedDate = String.format(
"${dateArray[0]}${
dateArray[0].toInt().ordinalAbbrev()
} ${dateArray[1]}"
)
return formatedDate
} catch (e: Exception) {
e.printStackTrace()
}
}
return date
}
public static String getReadableDate(final int date){
String suffix = "th";
switch (date){
case 1:
case 21:
case 31:
suffix = "st";
break;
case 2:
case 22:
suffix = "nd";
break;
case 3:
case 23:
suffix = "rd";
break;
}
return date + suffix;
}