1

I have a date formatted as 'yyMdd', where 'M' is a hexadecimal encoding of the month number (1 is January, C is December). How can I parse it to a java.util.Date? This is the same format as here, but a Java solution is required. Sure I can write a simple function for it myself but are there any existing parsers that handles this format?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
rockstarjindal
  • 293
  • 1
  • 5
  • 15
  • possible duplicate of [Format date in java](http://stackoverflow.com/questions/4772425/format-date-in-java) – Joe Oct 07 '14 at 13:53
  • @Joe The link you have given is not a duplicate because this question is about a very exotic date format not handled in the link. – Meno Hochschild Oct 07 '14 at 13:58

2 Answers2

2

You should try SimpleDataFormat from java.text:

First I would replace the Date String values for A, B & C by their equivalents 10, 11 & 12:

String yourDate = "14A07";

String day = StringUtils.substring(yourDate, 0, 2);

String month = StringUtils.substring(yourDate, 2, yourDate.length()-2);
month = month.replaceAll("A", "10").replaceAll("B", "11").replaceAll("C", "12");
if (month.length() == 1) {
    month = "0".concat(month);
}

String year = StringUtils.substring(yourDate, yourDate.length()-2, yourDate.length());

String adaptedDate = new StringBuilder(
    .append(day)
    .append(month)
    .append(year)
    .toString();

SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
Date date = sdf.parse(adaptedDate);
Mathias G.
  • 4,875
  • 3
  • 39
  • 60
  • It does not handle the date 14A10 i.e. 10 Oct 2014. This date format represent the months Oct, Nov and Dec as A, B, C respectively – rockstarjindal Oct 07 '14 at 12:15
  • It's wrong again, your original example doesn't work now i.e. 14110 is converted to 10/31/2014. We also need to pad zero to month. – rockstarjindal Oct 07 '14 at 12:33
2

With the class SimpleDateFormat you are forced to do some text preprocessing.

String input = "12B17T"; // according to the other SO-post
String month = input.substring(2, 3);

if (month.equals("A")) {
  month = "10";
} else if (month.equals("B")) {
  month = "11";
} else if (month.equals("C")) {
  month = "12";
} else {
  month = "0" + month;
}

String date = input.substring(0, 2) + month + input.substring(3, 5);
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
Date d = sdf.parse(date);

Another solution using Joda-Time might look like:

String input = "12B17T"; // according to the other SO-post

int pivotYear = 2032;
DateTimeParser monthParser =
    new DateTimeParser() {

        @Override
        public int estimateParsedLength() {
            return 1;
        }

        @Override
        public int parseInto(DateTimeParserBucket bucket, String text, int position) {
            DateTimeField field = ISOChronology.getInstance().monthOfYear();
            char c = text.charAt(position);

            if (c >= '1' && c <= '9') {
                int value = c - '0';
                bucket.saveField(field, value);
                return position + 1;
            }

            switch (c) {
                case 'A' :
                    bucket.saveField(field, 10);
                    break;
                case 'B' :
                    bucket.saveField(field, 11);
                    break;
                case 'C' :
                    bucket.saveField(field, 12);
                    break;

                default :
                    return ~position;
            }
            return position + 1;
        }
    };

DateTimeFormatter f =
  new DateTimeFormatterBuilder().appendTwoDigitYear(pivotYear - 50).append(monthParser)
  .appendDayOfMonth(2).appendLiteral('T').toFormatter();

LocalDate date = f.parseLocalDate(input);
System.out.println(date); // output: 2012-11-17

Surely this approach is not shorter or easier, but offers the advantage of immutability and hence thread-safety. Of course the same scheme can also be applied on other time libraries based on immutable types.

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126