Skip to content

Instantly share code, notes, and snippets.

@danieldietrich
Last active August 29, 2015 14:16
Show Gist options
  • Select an option

  • Save danieldietrich/1eb4f62b8f47f51c0662 to your computer and use it in GitHub Desktop.

Select an option

Save danieldietrich/1eb4f62b8f47f51c0662 to your computer and use it in GitHub Desktop.
A Date which is stable regarding hashCode, equals and compareTo
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* A UTC date, consisting of a year, a month and a day component. Compared to {@linkplain java.util.Date}
* a StableDate is stable regarding {@linkplain java.lang.Object#equals} and {@linkplain java.lang.Object#hashCode}.
*/
public class StableDate implements Comparable<StableDate>, Serializable {
private static final long serialVersionUID = 1L;
private final int year;
private final int month;
private final int day;
/**
* Creates a stable date based on a time in UTC milliseconds.
* @param millis the time in UTC milliseconds from the epoch.
* @return A new StableDate instance
*/
public static StableDate of(long millis) {
// java util date/time stuff is considered to be not thread safe - therefore creating new instances here
final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(millis);
final int year = calendar.get(Calendar.YEAR);
final int month = calendar.get(Calendar.MONTH) + 1;
final int day = calendar.get(Calendar.DAY_OF_MONTH);
return new StableDate(year, month, day);
}
/**
* Creates a stable date based on a UTC {@linkplain java.util.Date}.
* @param date A Date
* @return A new StableDate instance
*/
public static StableDate of(Date date) {
return StableDate.of(date.getTime());
}
/**
* Constructs a StableDate.
* @param year A year.
* @param month A month, starting with 1.
* @param day A day, starting with 1.
*/
StableDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
/**
* Gets this year.
* @return this year
*/
public int getYear() {
return year;
}
/**
* Gets this month.
* @return this month
*/
public int getMonth() {
return month;
}
/**
* Gets this day.
* @return this day
*/
public int getDay() {
return day;
}
/**
* Compares this and that StableDate.
* @param that A StableDate, may be null
* @return A negativ number, 0 or a positive number if this date is before, equal or after that date. If that is null, 1 is returned.
*/
@Override
public int compareTo(StableDate that) {
return (that == null) ? 1 : (this.year - that.year) * 10000 + (this.month - that.month) * 100 + (this.day - that.day);
}
/**
* Checks, if o equals this. An object o is equal to this, if o is an instance of StableDate and
* the year, month and day fields of this and o are respectively the same.
* @param o An object, may be null.
* @return true, if o equals this, false otherwise
*/
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof StableDate) {
final StableDate that = (StableDate) o;
return this.year == that.year && this.month == that.month && this.day == that.day;
} else {
return false;
}
}
/**
* Calculates the hash of this StableDate.
* @return {@code year * 10000 + month * 100 + day}
*/
@Override
public int hashCode() {
return year * 10000 + month * 100 + day;
}
/**
* Returns a String representation of this StableDate according to ISO 8601 format 'YYYY-MM-DD'.
* @return This date as String
*/
@Override
public String toString() {
return String.format("%04d-%02d-%02d", year, month, day);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment