Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 您如何将一个月中的某一天格式化为“日”;第十一条&引用;“21世纪”;或;第二十三条;(顺序指示符)?_Java_Date_Simpledateformat_Ordinal - Fatal编程技术网

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