2015-02-14 8 views
12

मैं SimpleDateFormat javadoc जाँच में एक तिथि के क्रमसूचक सूचक (सेंट, nd, आरडी, वें) पार्स, लेकिन मैं इस तरह की एक दिनांक स्वरूप में ordinal indicator पार्स करने के लिए एक रास्ता खोजने के लिए सक्षम नहीं हूँ:एक तारीख समय स्ट्रिंग

Feb 13th 2015 9:00AM 

मैंने "MMM dd yyyy hh:mma" की कोशिश की, लेकिन दिनों को सही होने के लिए संख्या में होना चाहिए?

क्या स्ट्रिंग को छेड़छाड़ किए बिना SimpleDateFormat का उपयोग करके "13 वीं" तारीख को पार्स करना संभव है?

+1

क्या तिथि भी 1, 2, 3 है .. ??? – Srinivasu

+0

हाँ सामान्य कैलेंडर की तरह – hao

+0

http://stackoverflow.com/questions/4011075/how-do-you-format-the-day-of-the-month-to-say-11th-21st-or-23rd- इन-जावा – Tom

उत्तर

15

जावा के SimpleDateFormat एक क्रमसूचक प्रत्यय का समर्थन नहीं करता है, लेकिन क्रमसूचक प्रत्यय बस आँख कैंडी है - यह अनावश्यक है और आसानी से एक सीधा पार्स अनुमति देने के लिए हटाया जा सकता है:

Date date = new SimpleDateFormat("MMM dd yyyy hh:mma") 
    .parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", "")); 

की जगह regex बहुत आसान है क्योंकि वे अनुक्रम मान्य तिथि में कहीं और नहीं दिखाई देंगे।


किसी भी भाषा है कि एक प्रत्यय के रूप में किसी भी भाषा से क्रमसूचक सूचक पात्रों में से किसी भी लम्बाई संलग्न कर देता है संभाल करने के लिए:

Date date = new SimpleDateFormat("MMM dd yyyy hh:mma") 
    .parse(str.replaceAll("(?<=\\d)(?=\\D* \\d+)\\p{L}+", "")); 

कुछ भाषाओं, जैसे अकर्मण्य, आगे जोड़ते उनके क्रमसूचक सूचक है, लेकिन वह भी नियंत्रित किया जा सकता है एक प्रत्यावर्तन का उपयोग कर - पाठक :)

+0

धन्यवाद, यह सबसे आसान समाधान की तरह लगता है। मुझे सच में उम्मीद है कि सरलीडेटफॉर्मेट एक दिन में सामान्य संख्या संभाल सकता है ... – hao

+1

@ हां मुझे नहीं लगता कि भविष्य में 'SimpleDateFormat' में सुधार किया जाएगा। अधिक संभावना है कि वे "जावा" के नए समय/दिनांक कक्षाओं पर काम करते हैं: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html। – Tom

+0

ध्यान दें कि यह केवल अंग्रेज़ी के लिए काम करता है। तो मैं इस धारणा को स्पष्ट करने के लिए लोकेल को निर्दिष्ट करने का सुझाव देता हूं। अन्य भाषाएं उनके [ordinal संकेतक] (http://en.m.wikipedia.org/wiki/Ordinal_indicator) के लिए अन्य मानों का उपयोग करती हैं। और अन्य भाषाएं उनके महीने के नाम में उन चार अंग्रेजी तारों में से किसी एक का उपयोग कर सकती हैं। शायद इस रेगेक्स को पहले नंबर पर जोड़े गए किसी भी गैर-अंकों को हटाने के लिए संशोधित किया जाएगा। –

4

जावा 8 जवाब (और जावा 6 और 7) (क्योंकि जब यह सवाल 2015 में पूछा गया था, SimpleDateFormat के लिए प्रतिस्थापन पहले से ही बाहर गया था) के लिए एक व्यायाम के रूप में छोड़ दिया:

012,351,
DateTimeFormatter parseFormatter = DateTimeFormatter 
      .ofPattern("MMM d['st']['nd']['rd']['th'] uuuu h:mma", Locale.ENGLISH); 
    LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, parseFormatter); 
सवाल यह yiedls से नमूना तारीख के साथ

:

2015-02-13T09:00 

प्रारूप पैटर्न [] में वैकल्पिक भागों को दर्शाता है और '' शाब्दिक भागों को दर्शाता है। तो पैटर्न कहता है कि संख्या st, nd, rd या th के बाद हो सकती है।

जावा 6 या 7 में इसका उपयोग करने के लिए आपको ThreeTen Backport की आवश्यकता है। या एंड्रॉइड ThreeTenABP के लिए।

चूंकि उन प्रत्यय अंग्रेजी के लिए विशेष हैं, और अन्य भाषाओं/लोकेशंस के पास दिनांक और समय लिखने के लिए पूरी तरह से अन्य उपयोग होते हैं (वे भी एएम/पीएम का उपयोग नहीं करते हैं), मुझे विश्वास है कि जब तक आपके पास अन्य आवश्यकताएं न हों, आपको कोशिश करनी चाहिए अंग्रेजी तिथियों और समय के लिए इसे लागू करने के लिए। इसके अलावा आपको स्पष्ट रूप से एक अंग्रेजी बोलने वाला लोकेल देना चाहिए ताकि यह आपके कंप्यूटर या जेवीएम की लोकेल सेटिंग से स्वतंत्र रूप से काम करे।

मैंने Hugo और myself द्वारा डुप्लिकेट प्रश्न के उत्तर के सर्वोत्तम भागों को गठबंधन करने का प्रयास किया है। that duplicate question के तहत अभी भी जावा 8 उत्तर हैं। उपर्युक्त कोड की एक सीमा यह है कि इसमें बहुत सख्त सत्यापन नहीं है: आप Feb 13rd और यहां तक ​​कि Feb 13stndrdth से दूर हो जाएंगे।

1

यदि किसी को यह उपयोगी लगता है: डेटटाइमफॉर्मेटर बिल्डर। यह फ़ॉर्मेटर आपको यूके तिथियों को क्रमिक प्रत्यय के साथ प्रारूपित करने और विश्लेषण करने की अनुमति देता है (उदाहरण के लिए।"1st जनवरी 2017"):

public class UkDateFormatterBuilder 
{ 
    /** 
    * The UK date formatter that formats a date without an offset, such as '14th September 2020' or '1st January 2017'. 
    * @return an immutable formatter which uses the {@link ResolverStyle#SMART SMART} resolver style. It has no override chronology or zone. 
    */ 
    public DateTimeFormatter build() 
    { 
     return new DateTimeFormatterBuilder() 
       .parseCaseInsensitive() 
       .parseLenient() 
       .appendText(DAY_OF_MONTH, dayOfMonthMapping()) 
       .appendLiteral(' ') 
       .appendText(MONTH_OF_YEAR, monthOfYearMapping()) 
       .appendLiteral(' ') 
       .appendValue(YEAR, 4) 
       .toFormatter(Locale.UK); 
    } 

    private Map<Long, String> monthOfYearMapping() 
    { 
     Map<Long, String> monthOfYearMapping = new HashMap<>(); 
     monthOfYearMapping.put(1L, "January"); 
     monthOfYearMapping.put(2L, "February"); 
     monthOfYearMapping.put(3L, "March"); 
     monthOfYearMapping.put(4L, "April"); 
     monthOfYearMapping.put(5L, "May"); 
     monthOfYearMapping.put(6L, "June"); 
     monthOfYearMapping.put(7L, "July"); 
     monthOfYearMapping.put(8L, "August"); 
     monthOfYearMapping.put(9L, "September"); 
     monthOfYearMapping.put(10L, "October"); 
     monthOfYearMapping.put(11L, "November"); 
     monthOfYearMapping.put(12L, "December"); 
     return monthOfYearMapping; 
    } 

    private Map<Long, String> dayOfMonthMapping() 
    { 
     Map<Long, String> suffixes = new HashMap<>(); 
     for (int day=1; day<=31; day++) 
     { 
      suffixes.put((long)day, String.format("%s%s", (long) day, dayOfMonthSuffix(day))); 
     } 
     return suffixes; 
    } 

    private String dayOfMonthSuffix(final int day) 
    { 
     Preconditions.checkArgument(day >= 1 && day <= 31, "Illegal day of month: " + 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"; 
     } 
    } 
} 

प्लस परीक्षण वर्ग का एक टुकड़ा:

public class UkDateFormatterBuilderTest 
{ 
    DateTimeFormatter formatter = new UkDateFormatterBuilder().build(); 

    @Test 
    public void shouldFormat1stJanuaryDate() 
    { 
     final LocalDate date = LocalDate.of(2017, 1, 1); 

     final String formattedDate = date.format(formatter); 

     Assert.assertEquals("1st January 2017", formattedDate); 
    } 

    @Test 
    public void shouldParse1stJanuaryDate() 
    { 
     final String formattedDate = "1st January 2017"; 

     final LocalDate parsedDate = LocalDate.parse(formattedDate, formatter); 

     Assert.assertEquals(LocalDate.of(2017, 1, 1), parsedDate); 
    } 
} 

पी एस। मैंने यहां से क्रमिक प्रत्यय के लिए ग्रेग मैट्स का समाधान किया: How do you format the day of the month to say "11th", "21st" or "23rd" in Java? (ordinal indicator)

0

आपको RuleBasedNumberFormat का उपयोग करना चाहिए। यह पूरी तरह से काम करता है और यह लोकेल का सम्मान करता है।

संबंधित मुद्दे