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.
3 Answers 3
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);
-
\$\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– Jason2015年02月22日 12:55:11 +00:00Commented Feb 22, 2015 at 12:55
-
\$\begingroup\$ Relevant \$\endgroup\$RubberDuck– RubberDuck2015年02月23日 03:25:48 +00:00Commented Feb 23, 2015 at 3:25
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
-
\$\begingroup\$ The incoming date is an integer, not a string, despite the statement that it's in YYYYmm format. \$\endgroup\$Pete Becker– Pete Becker2015年02月22日 07:27:43 +00:00Commented Feb 22, 2015 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 integer201502
. You can just convert that to a string and use this method. \$\endgroup\$ns47731– ns477312015年02月22日 07:30:50 +00:00Commented Feb 22, 2015 at 7:30
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).
-
\$\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– Jason2015年02月26日 16:11:49 +00:00Commented Feb 26, 2015 at 16:11
intMonth
, use the%
(modulus) operator. (2) Ditch Hungarian notation. \$\endgroup\$