Java 您如何格式化一个月中的某一天以表示“11 日”、“21 日”或“23 日”(序数指示符)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4011075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 08:21:02  来源:igfitidea点击:

How do you format the day of the month to say "11th", "21st" or "23rd" (ordinal indicator)?

javadatesimpledateformatordinal

提问by Ken Hume

I know this will give me the day of the month as a number (11, 21, 23):

我知道这会给我一个月中的某一天作为数字 ( 11, 21, 23):

SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d");

But how do you format the day of the month to include an ordinal indicator, say 11th, 21stor 23rd?

但是你如何格式化一个月中的某一天以包含一个序数指示符,比如说11th21st或者23rd

采纳答案by Greg Mattes

// 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 answerto see the error).

@kaliatech 的表格很好,但由于重复了相同的信息,因此可能会出现错误。这样的错误实际上在表中存在7tn17tn27tn(随着时间的推移,由于StackOverflow上的流体性质,所以检查这个错误可能会固定在答案的版本历史,看看错误)。

回答by kaliatech

There is nothing in JDK to do this.

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];

Or using Calendar:

或使用日历:

 Calendar c = Calendar.getInstance();
 c.setTime(date);
 int day = c.get(Calendar.DAY_OF_MONTH);
 String dayStr = day + suffixes[day];

Per comments by @thorbj?rn-ravn-andersen, a table like this can be helpful when localizing:

根据@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" };

回答by ocodo

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)];
}

回答by Erdem Memisyazici

There is a simpler and sure way of doing this. The function you'll need to use is getDateFromDateString(dateString); It basically removes the st/nd/rd/th off of a date string and simply parses it. You can change your SimpleDateFormat to anything and this will work.

有一种更简单且可靠的方法可以做到这一点。您需要使用的函数是 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;

}

}

回答by Anand Shekhar

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";
    }
}

回答by Simeon Hearring

public String getDaySuffix(int inDay)
{
  String s = String.valueOf(inDay);

  if (s.endsWith("1"))
  {
    return "st";
  }
  else if (s.endsWith("2"))
  {
    return "nd";
  }
  else if (s.endsWith("3"))
  {
    return "rd";
  }
  else
  {
    return "th";
  }
}

回答by Talisphere

Only issue with the solution provided by Greg is that it does not account for number greater than 100 with the "teen" numbers ending. For example, 111 should be 111th, not 111st. This is my solution:

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";
    }
}

回答by J888

The following is a more efficient answer to the question rather than hard-coding the style.

以下是对该问题的更有效的回答,而不是对样式进行硬编码。

To change the day to ordinal number you need to use the following suffix.

要将日期更改为序号,您需要使用以下后缀

DD +     TH = DDTH  result >>>> 4TH

OR to spell the number add SP to the format

DD + SPTH = DDSPTH   result >>> FOURTH

Find my completed answer in thisquestion.

这个问题中找到我完整的答案。

回答by C.A.B.

If you try to be aware of i18n the solution get even more complicated.

如果您尝试了解 i18n,解决方案会变得更加复杂。

The problem is that in other languages the suffix may depend not only on the number itself, but also on the noun it counts. For example in Russian it would be "2-ой день", but "2-ая неделя" (these mean "2nd day", but "2nd week"). This is not apply if we formatting only days, but in a bit more generic case you should be aware of complexity.

问题在于,在其他语言中,后缀可能不仅取决于数字本身,还取决于它所计数的名词。例如,在俄语中,它是“2-ой день”,而是“2-ая неделя”(这些意思是“第 2 天”,而是“第 2 周”)。如果我们只格式化几天,这不适用,但在更通用的情况下,您应该意识到复杂性。

I think nice solution (I didn't have time to actually implement) would be to extend SimpleDateFormetter to apply Locale-aware MessageFormat before passing to the parent class. This way you would be able to support let say for March formats %M to get "3-rd", %MM to get "03-rd" and %MMM to get "third". From outside this class looks like regular SimpleDateFormatter, but supports more formats. Also if this pattern would be by mistake applied by regular SimpleDateFormetter the result would be incorrectly formatted, but still readable.

我认为不错的解决方案(我没有时间实际实现)是在传递给父类之前扩展 SimpleDateFormetter 以应用 Locale-aware MessageFormat。这样你就可以支持让说三月格式 %M 获得“3-rd”, %MM 获得“03-rd”和 %MMM 获得“第三”。从外面看,这个类看起来像普通的 SimpleDateFormatter,但支持更多的格式。此外,如果此模式被常规 SimpleDateFormetter 错误地应用,结果将被错误地格式化,但仍然可读。

回答by sivag1

Many of the examples here will not work for 11, 12, 13. This is more generic and will work for all case.

这里的许多示例不适用于 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";
}