3
votes

I have a number of items with dates specified in MM/dd format, with no year specified.

However, the year is implied from the context of the data, since the data shows dates no older than 12 months from the "current date" (which is specified in the data)

For example, let's say the current date is January 31, 2013. This means that there will be information from February 1 2012 to January 31, 2013, inclusive.

The problem I'm facing here is, because there are no years specified in the data, I will need to generate the years myself before I load them into my database.

From the context of the data, we know that any dates greater than the current month is from the previous year, while any dates less than or equal to the current month is the current year.

So assuming current date is Jan 2013, we have things like

01/31 - 2013
01/01 - 2013
12/31 - 2012
02/29 - 2012

Now, the problem here is the date on the last line.

2012 was a leap year, so February 29 does exist. However, 2013 is not.

My current approach to date parsing is as follows (using SimpleDateFormat)

  1. Grab the date: 01/31
  2. Append the current year to it: 01/31/2016
  3. Parse the date using date format MM/dd/yyyy

Date parsing is performed under strict mode, so something like 02/29 isn't going to be rolled over to 03/01.

However, this algorithm fails on leap years, because assuming the current year is 2013, I'm going to try to parse 02/29/2013 and it will fail.

What is an approach I can use to determine the year of the date?

3
Your requirements are not clear. You show 1/31 as 2013 but 1/31/2012 is less than 12 months from the current date of 1/1/2012.JimmyJames
@JimmyJames I have added days for clarity.MxLDevs

3 Answers

3
votes

Parse the day/month to a java.time.MonthDay, compare it to MonthDay.now() and call atYear with the correct year (using Year.now() for example) depending on the result.

You may also want to take time zones into account.

A simple version applied to your example, assuming that the input is well formed and ignoring time zone issues, could look like:

public static void main(String[] args) {
  m("01/31", YearMonth.of(2013, 1));
  m("01/01", YearMonth.of(2013, 1));
  m("12/31", YearMonth.of(2013, 1));
  m("02/29", YearMonth.of(2013, 1));
}

private static void m(String date, YearMonth currentMonth) {
  DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd");
  MonthDay md = MonthDay.parse(date, fmt);
  int year = currentMonth.getYear();
  MonthDay cutoffDate = MonthDay.from(currentMonth.atEndOfMonth());
  if (md.isAfter(cutoffDate)) year--;
  LocalDate result = md.atYear(year);
  System.out.println(date + " - " + year + " ==> " + result);
}

which outputs:

01/31 - 2013 ==> 2013-01-31
01/01 - 2013 ==> 2013-01-01
12/31 - 2012 ==> 2012-12-31
02/29 - 2012 ==> 2012-02-29

2
votes

You cannot do it the way you want. You have to determine the year from the month and day before putting the whole thing into a Date. Here's some pseudocode assuming a date is always within the prior year, and a date equal to today is today and not 1 year ago (adjust as needed):

int cy = current year
int cm = current month
int cd = current day of month
int im = input month
int id = input day of month
int year = (im < cm || im==cm && id <= cd) ? cy : cy-1
try 
    Date d = new Date(year, im, id) strict
catch 
    invalid date
1
votes

So what about doing something like:

  1. Grab the date from your file.
  2. Append current year.
  3. Grab today's date.
  4. Compare today's date with the file's date. If today's date is before, then subtract a year from the files date.
  5. Parse the File Date.