development

달의 형식을 "11 일", "21 일"또는 "23 일"(표준 표시기)로 어떻게 지정합니까?

big-blog 2020. 6. 30. 07:59
반응형

달의 형식을 "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";
    }
}

질문이 조금 낡았습니다. 이 질문은 시끄럽기 때문에 정적 방법으로 해결 한 것을 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);
    }

자당 테스트

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

산출:

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

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

나는 현대의 답변에 기여하고 싶습니다. 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);
    }

이 스 니펫의 출력은 다음과 같습니다.

30th August
31st August
1st September
2nd September
3rd September
4th September

이전 답변

이 코드는 짧지 만 IMHO는 그렇게 우아하지 않습니다.

    // 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.


i18n을 알고 자하면 솔루션이 더욱 복잡해집니다.

문제는 다른 언어에서 접미사가 숫자 자체뿐만 아니라 계산되는 명사에도 의존 할 수 있다는 것입니다. 예를 들어 러시아어에서는 "2-ой день"이지만 "2-ая неделя"( "2 일째", "2 주차")입니다. 며칠 만 서식을 지정하는 경우에는 적용되지 않지만 좀 더 일반적인 경우에는 복잡성을 알고 있어야합니다.

좋은 해결책 (실제로 구현 할 시간이 없었습니다)은 부모 클래스에 전달하기 전에 SimpleDateFormetter를 확장하여 로케일 인식 MessageFormat을 적용하는 것입니다. 이렇게하면 3 월 형식 % M에서 "3rd"를, % MM에서 "03-rd"를, % MMM에서 "third"를 얻을 수 있습니다. 이 클래스 외부에서 일반 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을 사용해야합니다 . 완벽하게 작동하며 로케일을 존중합니다.


이 작업을 수행하는 더 간단하고 확실한 방법이 있습니다. 사용해야 할 함수는 getDateFromDateString (dateString)입니다. 기본적으로 날짜 문자열에서 st / nd / rd / th off를 제거하고 간단히 구문 분석합니다. 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;

}


Greg가 제공 한 솔루션의 유일한 문제는 "teen"으로 끝나는 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";
    }
}

다음은 패턴을 찾으면 올바른 접미어 리터럴로 DateTimeFormatter 패턴을 업데이트하는 방법입니다 ( d'00'예 : 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;
}

모든 형식 지정 호출 직전에 원본 패턴을 업데이트해야합니다. 예 :

public static String format(TemporalAccessor temporal, String pattern) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(updatePatternWithDayOfMonthSuffix(temporal, pattern));
    return formatter.format(temporal);
}

따라서 서식 패턴이 Java 코드 외부에서 정의 된 경우 (예 : 템플릿) Java에서 패턴을 정의 할 수있는 것처럼 @ OleV.V로 응답하는 경우에 유용합니다. 더 적절할지도 모른다


나는 이것에 대한 패턴을 얻는 도우미 방법을 내 자신에게 썼다.

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

kotlin에서는 다음과 같이 사용할 수 있습니다

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에서 이것이 필요한 경우이 답변을 확인할 수 있습니다

It's internationalized solution, though. And you don't need to reinvent the bicycle ;)


The following method can be used to get the formatted string of the date which is passed in to it. It'll format the date to say 1st,2nd,3rd,4th .. using SimpleDateFormat in Java. eg:- 1st of September 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);
        }

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 this question.


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

참고URL : https://stackoverflow.com/questions/4011075/how-do-you-format-the-day-of-the-month-to-say-11th-21st-or-23rd-ordinal

반응형