Month name in genitive (Polish locale) with Joda-Time DateTimeFormatter

后端 未结 2 1446
情书的邮戳
情书的邮戳 2020-12-15 05:18

I have LocalDate which contains date 2012-12-28 and I want to print it with localized month name (i.e. December in Polish) in genitive which in

相关标签:
2条回答
  • 2020-12-15 05:35

    Do you really need to use Joda? Replacing the month names is trivial using the date formatters in the standard Java API:

    SimpleDateFormat sdf = new SimpleDateFormat("'z dnia' dd MMMM yyyy 'r.'");
    
    DateFormatSymbols dfs = sdf.getDateFormatSymbols();
    
    dfs.setMonths(
        new String[] {
            "stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca",
            "lipca", "sierpnia", "września", "października", "listopada",
            "grudnia"   
        });
    
    sdf.setDateFormatSymbols(dfs);
    
    System.out.println(
       sdf.format(new GregorianCalendar(2012, Calendar.DECEMBER, 28).getTime()));
    
    0 讨论(0)
  • 2020-12-15 05:48

    You have my sympathies - the field system in Joda Time is somewhat complicated.

    However, I suggest that in this case the simplest approach would actually be to use DateTimeFormatterBuilder.append(DateTimePrinter printer). Note that this approach will only work if you're only interested in printing - if you need to parse as well, life becomes more complicated.

    At that point you only need to implement DateTimePrinter, which is relatively straightforward, particularly if you're happy to ignore the Locale as you're only interested in a single culture. You can put all the logic (not that there'll be much of it) in a single method, and make the rest of the methods just delegate to that method. For the overloads which take a long and a DateTimeZone, just construct a DateTime and call toLocalDateTime, at which point you can delegate to the other methods.

    EDIT: In fact, one option would be to write an abstract base class, if you knew you'd only care about the local values:

    public abstract class SimpleDateTimePrinter implements DateTimePrinter {
    
        protected abstract String getText(ReadablePartial partial, Locale locale);
    
        @Override
        public void printTo(StringBuffer buf, long instant, Chronology chrono,
                int displayOffset, DateTimeZone displayZone, Locale locale) {
            DateTime dateTime = new DateTime(instant, chrono.withZone(displayZone));
            String text = getText(dateTime.toLocalDateTime(), locale);
            buf.append(text);
        }
    
        @Override
        public void printTo(Writer out, long instant, Chronology chrono,
                int displayOffset, DateTimeZone displayZone, Locale locale)
                throws IOException {
            DateTime dateTime = new DateTime(instant, chrono.withZone(displayZone));
            String text = getText(dateTime.toLocalDateTime(), locale);
            out.write(text);
        }
    
        @Override
        public void printTo(StringBuffer buf, ReadablePartial partial, Locale locale) {
            buf.append(getText(partial, locale));
        }
    
        @Override
        public void printTo(Writer out, ReadablePartial partial, Locale locale)
                throws IOException {
            out.write(getText(partial, locale));
        }
    }
    

    Then you can easily write a concrete subclass which ignores the locale, and just returns the month:

    public class PolishGenitiveMonthPrinter extends SimpleDateTimePrinter {
    
        private static final ImmutableList<String> MONTH_NAMES =
                ImmutableList.of(
                    "stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca",
                    "lipca", "sierpnia", "września", "października", "listopada",
                    "grudnia");
    
        private static final int MAX_MONTH_LENGTH;
    
        static {
            int max = 0;
            for (String month : MONTH_NAMES) {
                if (month.length() > max) {
                    max = month.length();
                }
            }
            MAX_MONTH_LENGTH = max;
        }
    
        @Override
        public int estimatePrintedLength() {
            return MAX_MONTH_LENGTH;
        }
    
        @Override
        protected String getText(ReadablePartial partial, Locale locale) {
            int month = partial.get(DateTimeFieldType.monthOfYear());
            return MONTH_NAMES.get(month - 1);
        }
    }
    

    Of course you could do this all in one class, but I'd probably break it out to make the base class more reusable in the future.

    0 讨论(0)
提交回复
热议问题