คุณจัดรูปแบบวันในเดือนนั้นเพื่อพูดว่า "11th", "21" หรือ "23" (ตัวบ่งชี้ลำดับ) อย่างไร


146

ฉันรู้ว่านี้จะให้ฉันวันของเดือนเป็นตัวเลข ( 11, 21, 23):

SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d");

แต่อย่างไรคุณจัดรูปแบบวันที่ของเดือนที่จะมีตัวบ่งชี้ลำดับการพูด11th, 21stหรือ23rd?


13
สำหรับการอ้างอิงเหล่านี้เรียกว่าหมายเลขลำดับ - en.wikipedia.org/wiki/Ordinal_number_(linguistics)
ocodo

5
เพียงบันทึกสิ่งใดก็ตามที่สร้างการตอบสนองแทนที่จะมองหาคำตอบทั้งหมดในตารางนั้นใกล้จะเป็นไปไม่ได้ที่จะแปลเป็นภาษาอื่น
Thorbjørn Ravn Andersen

2
คำตอบนั้นไม่ถูกต้องมีลักษณะที่คำตอบของฉันนะ
J888

2
ความคิดเห็นที่ทันสมัย: ฉันแนะนำให้คุณหลีกเลี่ยงการSimpleDateFormatเรียน ไม่เพียง แต่ล้าสมัยมานานเท่านั้น แต่ยังเป็นปัญหาที่ฉาวโฉ่ วันนี้เรามีมากดีกว่าในการjava.timeที่ทันสมัย Java วันที่และเวลา APIDateTimeFormatterและ
Ole VV

ดูตัวเลข API ( math.tools/api/numbers ) มันมีการสนับสนุนสำหรับลำดับ, สำคัญ, หมายเลขที่สะกดออกมาในภาษาที่แตกต่างกัน, สะกดออกมาเป็นสกุลเงินในภาษาต่าง ๆ ฯลฯ
dors

คำตอบ:


181
// 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 เพื่อตรวจสอบประวัติรุ่นในคำตอบที่จะเห็นข้อผิดพลาด)


36
มันให้ความรู้สึกเหมือนการกำกับดูแลในรูปแบบข้อมูลอย่างง่ายใช่ไหม?
stevevls

51
ขอให้สนุกกับการทำสิ่งนี้ให้เป็นสากล : D
Trejkaz

6
@Trejkaz นอกขอบเขตของคำถาม :)
เกร็ก Mattes

3
โซลูชันนี้รองรับเฉพาะภาษาอังกฤษ ใช้ RuleBasedNumberFormat จาก ICU4J สำหรับโซลูชันที่แปลเป็นภาษาท้องถิ่น
ДмитроЯковлєв

7
พวกคุณอยู่ในวัชพืชและน้ำเสียงเปลี่ยนไปเล็กน้อย ไม่จำเป็นสำหรับสิ่งนั้น คำถามนี้ไม่ได้ถามเกี่ยวกับความซับซ้อนของความเป็นสากล การทำให้เป็นสากลเป็นหัวข้อที่ดีในการพูดคุย แต่ควรทำในคำถามอื่นที่มุ่งเน้น ฉันมักจะตีความคำถามนี้เพื่อขอวิธีที่รวดเร็วและสกปรกในการทำสิ่งนี้เป็นภาษาอังกฤษ ดังนั้นฉันขอแนะนำว่าถ้าไม่มีทางออกที่ดีในโลก Java ที่เป็นสากลที่เป็นมิตรที่เราเริ่มโครงการเช่น GitHub และสร้างทางออกที่ดี แจ้งให้เราทราบหากคุณสนใจ
Greg Mattes

51

ไม่มีสิ่งใดใน 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" };

8
หากคุณปล่อยให้ตารางมี "21" เต็ม "23", "29" เต็มรูปแบบสามารถถูกทำให้เป็นภายนอกและแปลเป็นภาษาอื่น ๆ สำหรับซอฟต์แวร์ที่ประสบความสำเร็จซึ่งอาจเป็นข้อกำหนด
Thorbjørn Ravn Andersen

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

ฉันเพิ่งลองวิธีแก้ปัญหาของคุณในขณะที่ละเว้นคำพูดเดียวในสตริงรูปแบบที่มีให้กับตัวสร้าง SimpleDateFormat ตอนนี้ฉันเห็นว่าทำไมพวกเขาถึงอยู่ที่นั่น ฉันได้รับjava.lang.IllegalArgumentExceptionเพราะ "ตัวละครรูปแบบที่ผิดกฎหมายต.
พี่เลี้ยงทั่วไป

17

คำถามเก่าไปนิด เนื่องจากคำถามนี้มีเสียงดังมากดังนั้นโพสต์สิ่งที่ฉันได้แก้ไขด้วยวิธีการคงที่เป็นประโยชน์ เพียงแค่คัดลอกวางและใช้งาน!

 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

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

14

ฉันต้องการที่จะสนับสนุนคำตอบที่ทันสมัย 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ฯลฯ นั่นได้ทำในคำถามนี้: ชวา - วันที่แยกกับตัวเลือกวินาที

Link: ออราเคิลกวดวิชา: วันที่เวลาjava.timeอธิบายวิธีการใช้งาน


จะรักที่จะได้คำตอบนี้กระแทกสูงขึ้นเพราะคำตอบที่ทันสมัยกว่านี้จะดีกว่าการพยายามที่จะย้อนการใช้งานของคุณเอง
Krease

9

หากคุณพยายามระวัง i18n การแก้ปัญหาก็จะยิ่งซับซ้อนมากขึ้น

ปัญหาคือในภาษาอื่น ๆ คำต่อท้ายอาจไม่เพียง แต่ขึ้นอยู่กับจำนวนตัวมันเองเท่านั้น แต่ยังรวมถึงคำนามด้วย ตัวอย่างเช่นในภาษารัสเซียมันจะเป็น "2-ойдень" แต่ "2-аянеделя" (หมายถึง "วันที่ 2" แต่ "สัปดาห์ที่ 2") สิ่งนี้ใช้ไม่ได้หากเราทำการจัดรูปแบบวันเท่านั้น แต่ในกรณีทั่วไปอีกเล็กน้อยคุณควรตระหนักถึงความซับซ้อน

ฉันคิดว่าวิธีแก้ปัญหาที่ดี (ฉันไม่มีเวลานำไปใช้จริง) จะเป็นการขยาย SimpleDateFormetter เพื่อใช้ MessageFormat ที่รับรู้สถานที่ก่อนที่จะผ่านไปยังคลาสพาเรนต์ วิธีนี้คุณจะสามารถสนับสนุนให้พูดสำหรับรูปแบบเดือนมีนาคม% M เพื่อรับ "3-rd",% MM เพื่อรับ "03-rd" และ% MMM เพื่อรับ "สาม" จากภายนอกคลาสนี้ดูเหมือน SimpleDateFormatter ปกติ แต่รองรับรูปแบบเพิ่มเติม นอกจากนี้หากรูปแบบนี้จะเกิดจากความผิดพลาดที่ใช้โดย SimpleDateFormetter ปกติผลลัพธ์จะถูกจัดรูปแบบไม่ถูกต้อง แต่ก็ยังสามารถอ่านได้


จุดที่ดีเกี่ยวกับเพศในรัสเซีย แต่ในทางเทคนิคแล้วจะทำให้% MMM เป็นไปไม่ได้หากไม่มีบริบทเพิ่มเติม
นักฟิสิกส์บ้า

@Mad Physicist สิ่งนี้ไม่เป็นความจริงเนื่องจาก% MMM จะถูกนำไปใช้กับเดือนดังนั้นเราจึงรู้คำนามในการผัน
CAB

6

ตัวอย่างจำนวนมากในที่นี้จะไม่ทำงานสำหรับ 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";
}

5

ฉันไม่พอใจกับคำตอบสำหรับการแก้ปัญหาภาษาอังกฤษอย่างเดียวตามรูปแบบคู่มือ ฉันกำลังมองหาวิธีการแก้ปัญหาที่เหมาะสมในขณะนี้และในที่สุดก็พบมัน

คุณควรจะใช้RuleBasedNumberFormat มันทำงานได้อย่างสมบูรณ์และเป็นที่เคารพของสถานที่


3

มีวิธีที่ง่ายและมั่นใจในการทำเช่นนี้ ฟังก์ชั่นที่คุณต้องใช้คือ 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;

}


1
คำตอบนี้เกี่ยวกับการแยกสตริงในขณะที่คำถามเกี่ยวกับการสร้างสตริง แต่ยังคงเหมาะสมเนื่องจากมีแนวโน้มว่าจะต้องการทั้งสองทิศทาง นอกจากนี้คำตอบนี้ยังแก้คำถามอื่นอีกด้วย
Basil Bourque

3

ปัญหาเฉพาะของโซลูชันที่ Greg จัดเตรียมไว้ให้คือมันไม่ได้หมายถึงหมายเลขที่มากกว่า 100 ด้วยหมายเลข "teen" ที่ลงท้ายด้วย ตัวอย่างเช่น 111 ควรเป็น 111th ไม่ใช่ 111st นี่คือทางออกของฉัน:

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

6
ลำดับวันรายเดือนจะมีอะไรมากกว่า 31 วัน
SatanEnglish

@ SatanEnglish ภาษาอังกฤษสิ่งที่ดีเกี่ยวกับวิธีการที่โรงงานแบบคงที่นี้คือมันสามารถใช้งานได้นานกว่าแค่การต่อท้ายของเดือน :)
Jared Rummler

1
วิธีนี้จะคืนค่า st 11, nd สำหรับ 12 และ rd สำหรับ 13
TheIT

@SatanEnglish ระบุว่าวันนี้เป็นวันที่ 137 กุมภาพันธ์ในปฏิทินที่ฉันเลือกฉันคิดว่าคำถามของคุณตอบเอง อย่างจริงจังแม้ว่าปฏิทินที่ไม่ใช่คริสต์ศักราชจะมีอยู่มากมายหากคุณรู้ว่าต้องมองที่ไหน
นักฟิสิกส์บ้า

ไม่ @ TheIT ไม่เป็นเช่นนั้น ฉันทดสอบแล้ว มันกลับมาthเป็น 11, 12 และ 13 เท่าที่ควร ฉันเชื่อว่าif ( hunRem - tenRem == 10 )กรณีทำให้แน่ใจ
Ole VV

2

RuleBasedNumberFormat ในห้องสมุด ICU

ฉันชื่นชมลิงก์ไปยังห้องสมุดของโครงการ ICU จาก @ Pierre-Olivier Dybman ( http://www.icu-project.org/apiref/icu4j/com/ibm/icu/text/RuleBasedNumberFormat.html ) แต่ก็ยังต้องคิด วิธีการใช้งานดังนั้นตัวอย่างของการRuleBasedNumberFormatใช้งานอยู่ด้านล่าง

มันจะจัดรูปแบบหมายเลขเดียวมากกว่าทั้งวันดังนั้นคุณจะต้องสร้างสตริงที่รวมกันหากค้นหาวันที่ในรูปแบบ: วันจันทร์ที่ 3 กุมภาพันธ์เป็นต้นไป

รหัสด้านล่างตั้งค่าRuleBasedNumberFormatรูปแบบ Ordinal สำหรับ Locale ที่กำหนดสร้างjava.time ZonedDateTimeและจัดรูปแบบตัวเลขโดยใช้เลขลำดับเป็นสตริง

RuleBasedNumberFormat numOrdinalFormat = new RuleBasedNumberFormat(Locale.UK,
    RuleBasedNumberFormat.ORDINAL);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Pacific/Auckland"));

String dayNumAndOrdinal = numOrdinalFormat.format(zdt.toLocalDate().getDayOfMonth());

ตัวอย่างผลลัพธ์:

3

หรือ

4

เป็นต้น


1

นี่คือวิธีการที่ปรับปรุงรูปแบบ 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 อาจเหมาะสมกว่า


1
ความคิดสร้างสรรค์และซับซ้อน แน่นอนว่าฉันใช้เวลานานกว่าจะเข้าใจวิธีการทำงาน นั่นไม่ใช่สัญญาณของรหัสที่ดี
Ole VV

1
@ OleV.V ขอบคุณสำหรับคำติชม - ฉันได้ปรับโครงสร้างมันเล็กน้อยดังนั้นมันจึง verbose น้อยลงเล็กน้อย เพิ่งเห็นแนวทางของคุณและฉันชอบมัน! ฉันคิดว่าวิธีการทั้งสองใช้ได้กับการแลกเปลี่ยนที่แตกต่างกัน ของคุณไม่ต้องการการสนับสนุนเพิ่มเติมใด ๆ ณ จุดของการจัดรูปแบบ แต่ไม่ต้องการรูปแบบที่กำหนดโดยใช้ตัวสร้างที่จำกัดความของรูปแบบในโค้ด Java ที่ไม่ใช่ วิธีการของฉันต้องการการสนับสนุนเพิ่มเติม ณ จุดของการจัดรูปแบบ แต่ไม่มีการพึ่งพาตัวสร้างเพื่อสร้างรูปแบบจึงทำให้มีความยืดหยุ่นมากขึ้นเล็กน้อยซึ่งสามารถกำหนดรูปแบบได้ ความต้องการของฉันบอกหลัง
tazmaniax

3
บัญชีข้อดีและข้อเสียที่ดีมาก คุณอาจต้องการรวมไว้ในคำตอบ? แค่ความคิด
Ole VV

1

ฉันเขียนวิธีช่วยเหลือตัวเองเพื่อหารูปแบบสำหรับสิ่งนี้

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

สิ่งนี้ต้องใช้ API ขั้นต่ำที่ 26 แม้ว่า :)
Mikkel Larsen

@ MikkelLarsen คำถามนี้ไม่เกี่ยวกับ android ฉันใช้ Java 8 สำหรับสิ่งนี้ Android ไม่รองรับ api ขนาดใหญ่สำหรับ java 8
SamHoque

@SamSakerz ไม่ดีของฉัน :)
Mikkel เสน

@MikkelLarsen ส่วนใหญ่java.timeการทำงานจะกลับรังเพลิง Java 6 & Java 7 ในThreeTen-ย้ายกลับโครงการ ดัดแปลงเพิ่มเติมสำหรับก่อนหน้านี้ Android (<26) ในThreeTenABP ดูวิธีการใช้ ThreeTenABP … .
Basil Bourque

1

ลองฟังก์ชั่นด้านล่าง:

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

เมื่อตอบคำถามเก่าคำตอบของคุณจะมีประโยชน์มากกว่าสำหรับผู้ใช้ StackOverflow รายอื่นหากคุณรวมบริบทบางอย่างเพื่ออธิบายว่าคำตอบของคุณช่วยได้อย่างไรโดยเฉพาะอย่างยิ่งสำหรับคำถามที่มีคำตอบที่ยอมรับแล้ว ดู: ฉันจะเขียนคำตอบที่ดีได้อย่างไร
เดวิดบั๊ก

ขอบคุณที่ต้องการมีส่วนร่วม ผมขอแนะนำให้เราไม่ได้ใช้Date, และCalendar SimpleDateFormatคลาสเหล่านั้นได้รับการออกแบบมาไม่ดีและล้าสมัยไปนาน แทนที่จะใช้LocalDateและDateTimeFormatterทั้งจากjava.time ทันสมัย Java วันที่และเวลา API ฉันยังมีข้อสงสัยว่าคำตอบของคุณมีส่วนช่วยอะไรใหม่เมื่อเทียบกับอีก 18 คำตอบ?
Ole VV

0

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

-3

วิธีการต่อไปนี้สามารถใช้ในการรับสตริงที่จัดรูปแบบของวันที่ซึ่งจะถูกส่งผ่านไป มันจะจัดรูปแบบวันที่ที่จะบอกว่า 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);
        }

-4

ต่อไปนี้เป็นคำตอบสำหรับคำถามที่มีประสิทธิภาพมากกว่าการเขียนโค้ดแบบยาก

ในการเปลี่ยนวันที่จะเลขลำดับที่คุณจำเป็นต้องใช้ต่อไปต่อท้าย

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

OR to spell the number add SP to the format

DD + SPTH = DDSPTH   result >>> FOURTH

หาคำตอบแล้วเสร็จของฉันในนี้คำถาม


คำถามคือการจัดรูปแบบใน Java ไม่ได้อยู่ในฐานข้อมูล Oracle docs.oracle.com/cd/B12037_01/server.101/b10759/… Java ใช้ SimpleDateFormat สำหรับวันที่: docs.oracle.com/javase/tutorial/i18n/format/ …
Belal mazlom

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

ไม่ควรใช้ endsWith (); ซึ่งให้ผลลัพธ์ที่ผิด
Rahul Sharma
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.