Как вы форматируете день месяца, чтобы сказать «11-й», «21-й» или «23-й» (порядковый индикатор)?

Я знаю, что это даст мне день месяца как число ( 11 , 21 , 23 ):

 SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d"); 

Но как вы форматируете день месяца, чтобы включить порядковый индикатор , например, 11th , 21st или 23rd ?

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

    Таблица из @kaliatech хороша, но так как повторяется одна и та же информация, она открывает шанс на ошибку. Такая ошибка действительно существует в таблице для 7tn , 17tn и 27tn (эта ошибка может быть исправлена ​​с течением времени из-за жидкого характера StackOverflow, поэтому проверьте историю версий в ответе, чтобы увидеть ошибку).

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

    Или используя Календарь:

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

    Вопрос немного стар. Поскольку этот вопрос очень шумный, поэтому отправляю то, что я решил с помощью статического метода в качестве утилиты. Просто скопируйте, вставьте и используйте его!

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

    Для тестирования purose

    Пример: вызов его из основного метода!

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

    Вывод:

     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 

    Если вы попытаетесь осознать i18n, решение станет еще более сложным.

    Проблема в том, что в других языках суффикс может зависеть не только от самого числа, но и от существительного, которое он считает. Например, по-русски это будет «2-ой день», но «2-ая неделя» (это означает «2-й день», но «2-я неделя»). Это не применяется, если мы форматируем только дни, но в более общем случае вы должны знать о сложности.

    Я думаю, что хорошее решение (у меня не было времени, чтобы на самом деле реализовать) было бы расширение SimpleDateFormetter для применения Local-aware MessageFormat перед передачей родительскому classу. Таким образом, вы сможете поддержать, допустив, что в марте форматы% M получат «3-й»,% MM, чтобы получить «03-й» и% MMM, чтобы получить «третий». Снаружи этот class выглядит как обычный 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"; } 

    Я не могу быть удовлетворен ответами, требующими решения на английском языке, основанного на ручных форматах. Некоторое время я искал подходящее решение, и наконец нашел его.

    Вы должны использовать RuleBasedNumberFormat . Он отлично работает и уважает Locale.

    Существует более простой и верный способ сделать это. Функция, которую вам нужно использовать, – 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; 

    }

    Только проблема с решением, предоставленным Грегом, заключается в том, что он не учитывает число, большее 100, при этом заканчиваются «подростковые» числа. Например, 111 должен быть 111-м, а не 111-м. Это мое решение:

     /** * Return ordinal suffix (eg '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"; } } 

    Я хотел бы внести современный ответ. Класс SimpleDateFormat был в порядке, когда вопрос был задан почти 8 лет назад, но вы должны избегать его сейчас, поскольку он не только давно устарел, но и печально известен. java.time этого используйте java.time :

      // 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()]); 

    Запуск этого fragmentа сейчас я получил

    двадцать третий

    Одна из многих функций java.time – это простой и надежный java.time получить день месяца как int , что, очевидно, необходимо для выбора нужного суффикса из таблицы.

    Я рекомендую вам также написать единичный тест.

    Ссылка: Учебник Oracle: Дата Время, объясняющее, как использовать java.time .

    В котлине вы можете так использовать

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

    Если вам это нужно на Android, вы можете проверить этот ответ

    Это интернационализированное решение. И вам не нужно изобретать велосипед;)

    Ниже приведен более эффективный ответ на вопрос, а не жесткое кодирование стиля.

    Чтобы изменить день на порядковый номер, вам необходимо использовать следующий суффикс .

     DD + TH = DDTH result >>>> 4TH OR to spell the number add SP to the format DD + SPTH = DDSPTH result >>> FOURTH 

    Найдите мой завершенный ответ в этом вопросе.

    Следующий способ может использоваться для получения форматированной строки даты, которая ему передается. Он будет форматировать дату, чтобы сказать 1, 2, 3, 4 … используя SimpleDateFormat в Java. например: – 1 сентября 2015 года

     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); } 
     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"; } } 
    Давайте будем гением компьютера.