8
\$\begingroup\$

Due to some clueless soul, we have several fields in a legacy database that uses a 6-digit integer to represent a date in (YYYYmm) format. The date field is assumed to be the last day of the given month.

I have written the following method to perform the conversion from int to java.util.Date:

public Date convertIntToDate(Integer intDate) {

    if (intDate < 100000 || intDate > 999999) {
        log.warn("Unable to parse int date {}", intDate);
        return null;
    }

    int intYear = intDate/100;
    int intMonth = intDate - (intYear * 100);

    Calendar result = new GregorianCalendar();
    result.set(intYear, intMonth - 1, 1, 0, 0, 0);

    return result.getTime();
}

It seems to work, but if anyone has any suggested improvements, I'd love to hear them.

\$\endgroup\$
  • 1
    \$\begingroup\$ (1) To get intMonth, use the % (modulus) operator. (2) Ditch Hungarian notation. \$\endgroup\$ – Cole Johnson Feb 22 '15 at 3:50
  • \$\begingroup\$ What you may and may not do after receiving answers. I've rolled back Rev 3 → 2. \$\endgroup\$ – 200_success Feb 22 '15 at 17:17
  • \$\begingroup\$ Thanks. In fact, I'll even go one better and mark the whole thing for deletion. \$\endgroup\$ – Jason Feb 23 '15 at 13:43
7
\$\begingroup\$

The date field is assumed to be the last day of the given month.

This seems to suggest that you would want to convert 201502 to 2015 Feb 28, as that's the last day of 2015 Feb. Your code converts to 2015 Feb 01, I hope that's what you really meant.

Your validation is too weak:

if (intDate < 100000 || intDate > 999999) {
    log.warn("Unable to parse int date {}", intDate);
    return null;
}

So, 999999 is a valid date? The method will convert that to 10007-03-01.

What about 201599? The method will convert that to 2023-03-01. Not so great.

I'd suggest to do the validation after converting to intYear and intMonth. It will be easier to follow and more logical.

Why does the method take an Integer? It doesn't make sense, and it makes the method prone to NullPointerException. (The code will throw when reaching intDate < 100000 in the if condition.)

The conversion to month would be more readable with a modulo:

    int intMonth = intDate % 100;

And the way you set the month is incorrect, as the second value of result.set is supposed to be a constant like Calendar.JANUARY. The correct way:

    result.set(Calendar.YEAR, intYear);
    result.set(Calendar.MONTH, intMonth - 1);
    result.set(Calendar.DAY_OF_MONTH, 1);
\$\endgroup\$
  • \$\begingroup\$ The method take Integer instead of int because the input could potentially be null (nullable database field). However, I screwed up by not checking for a null input, which I've fixed. \$\endgroup\$ – Jason Feb 22 '15 at 12:55
  • \$\begingroup\$ Relevant \$\endgroup\$ – RubberDuck Feb 23 '15 at 3:25
6
\$\begingroup\$

Any time I see numbers being thrown around in dates I get scared. Dates are confusing and there are some very strange things that happen (leap years, time zones you name it).

I would go with using a SimpleDateFormat and Calendar

String dateString = "201502";

// format for year and month
SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
// parse the date
Date date = format.parse(dateString);

Calendar cal = Calendar.getInstance();
cal.setTime(date);
// make it the last day of that month
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));

System.out.println(cal.getTime()); // Sat Feb 28 00:00:00 PST 2015
\$\endgroup\$
  • \$\begingroup\$ The incoming date is an integer, not a string, despite the statement that it's in YYYYmm format. \$\endgroup\$ – Pete Becker Feb 22 '15 at 7:27
  • \$\begingroup\$ @PeteBecker I interpreted that it was an integer that was in the form of year*100+month so todays date would be an integer 201502. You can just convert that to a string and use this method. \$\endgroup\$ – ns47731 Feb 22 '15 at 7:30
0
\$\begingroup\$

If you are using Java 8, then please use the new java.time package instead of the old and crappy java.util.Calendar and java.util.Date classes. There is a class java.time.YearMonth which is exactly meant for what you need - storing a year and month.

int number = 201502;
YearMonth ym = YearMonth.of(number / 100, number % 100);

Note that YearMonth.of checks if its arguments are valid, it will throw a DateTimeException if they're not (for example if the month is a number < 1 or > 12).

If you are not using Java 8, consider using Joda Time which has a similar class (in fact, Java 8's new date and time API is based on Joda Time).

\$\endgroup\$
  • \$\begingroup\$ Java 8... oh, such a dream. Code has to be written to Java 6 specs (regardless of what JDK version we are using). At least it's not Java 1.4... Oh, and our project lead dislikes Joda. \$\endgroup\$ – Jason Feb 26 '15 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.