简体   繁体   中英

How to strictly parse a date with only a year and a week number when the first day of this week is in the previous year?

My goal is to have a strict parsing (and forbid dates like '98/99' for example). However, the following code raises a java.text.ParseException with the message Unparseable date: "98/01" :

SimpleDateFormat sdf = new SimpleDateFormat("yy/ww");
sdf.setLenient(false);
sdf.parse("98/01");

This is indeed for the first week of 1998 , which starts on a Thursday. However, the parsing of a week always returns the date of the first day of this week. In that case, it would be 12/29/1997 . And this is why an exception is raised.

It seems this problem comes from the GregorianCalendar class and more specifically from the computeTime() method which checks if the original fields match the fields externally set when the parsing is not lenient :

if (!isLenient()) {
  for (int field = 0; field < FIELD_COUNT; field++) {
    if (!isExternallySet(field)) {
      continue;
    }

    if (originalFields[field] != internalGet(field)) {
      // Restore the original field values
      System.arraycopy(originalFields, 0, fields, 0, fields.length);
      throw new IllegalArgumentException(getFieldName(field));
    }
  }
}

Is this a bug? I think parsing 1998/01 should indeed return 12/29/1997 and not raise any exception. However, do you know how to make the parsing returns 01/01/1998 instead (which would be the first day of the week in the specified year)?

I think this should work for you (you need the library joda time for this):

public static Date parseYearWeek(String yearWeek) {
    DateTime dateTime = DateTimeFormat.forPattern("yy/ww").parseDateTime(yearWeek);

    if (dateTime.getWeekOfWeekyear() == 1 && dateTime.getMonthOfYear() == 12) {
        dateTime = DateTimeFormat.forPattern("yyyy/mm").parseDateTime((dateTime.getYear() + 1) + "/01");
    }

    return dateTime.toDate();
}

You could use Thursday as a reference, subtract 3 days to calculate the date of Monday. ISO 8601 definition of week 1 is the first week where Thursday occurs. This will eliminate the compensating code. The code below will find the Monday in a week, even if Monday is in the "previous" year.

String yearWeek = "201301";
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyywwEEE").withLocale(Locale.US);
DateTime mondayInWeek= fmt.parseDateTime(yearWeek + "Thu").minusDays(3);// ISO 8601 def of week 1 is first week where Thursday occurs
System.out.println(mondayInWeek);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM