package ilarkesto.base.time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.TimeZone;
public final class DateAndTime implements Comparable<DateAndTime> {
public static final transient SimpleDateFormat FORMAT_WEEKDAY_DAY_LONGMONTH_YEAR_HOUR_MINUTE = new SimpleDateFormat(
"EEE, dd. MMMM yyyy, HH:mm");
public static final transient SimpleDateFormat FORMAT_WEEKDAY_LONGMONTH_DAY_YEAR_HOUR_MINUTE = new SimpleDateFormat(
"EEE, MMM d, yyyy, HH:mm");
public static final transient SimpleDateFormat FORMAT_DAY_MONTH_YEAR_HOUR_MINUTE = new SimpleDateFormat(
"dd.MM.yyyy, HH:mm");
public static final transient SimpleDateFormat FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
public static final transient SimpleDateFormat FORMAT_LOG = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
public static final transient SimpleDateFormat FORMAT_RFC822 = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z",
Locale.ENGLISH);
private Date date;
private Time time;
public DateAndTime(java.util.Date date) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(date);
this.date = new Date(calendar);
this.time = new Time(calendar);
}
public DateAndTime(long millis) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(millis);
this.date = new Date(calendar);
this.time = new Time(calendar);
}
public DateAndTime(GregorianCalendar calendar) {
this(new Date(calendar), new Time(calendar));
}
public DateAndTime(Date date, Time time) {
this.date = date;
this.time = time;
}
public DateAndTime(int year, int month, int day, int hour, int minute, int second) {
this(new Date(year, month, day), new Time(hour, minute, second));
}
public DateAndTime(String s) {
StringTokenizer tok = new StringTokenizer(s, " ");
if (!tok.hasMoreElements()) throw new RuntimeException("Invalid DateAndTime format: " + s);
date = new Date(tok.nextToken());
if (tok.hasMoreElements()) {
time = new Time(tok.nextToken());
} else {
time = new Time(0, 0);
}
}
/**
* Assume instance as in given time zone and convert to UTC.
*/
public DateAndTime toUtc(TimeZone timeZone) {
long millis = toMillis();
int offset = timeZone.getOffset(millis);
return new DateAndTime(millis - offset);
}
/**
* Assume instance as in UTC and convert to given time zone.
*/
public DateAndTime toTimezone(TimeZone timeZone) {
long millis = toMillis();
int offset = timeZone.getOffset(millis);
return new DateAndTime(millis + offset);
}
public DateAndTime addDays(int days) {
GregorianCalendar gc = toGregorianCalendar();
gc.add(GregorianCalendar.DAY_OF_YEAR, days);
return new DateAndTime(gc);
}
public DateAndTime addHours(int hours) {
GregorianCalendar gc = toGregorianCalendar();
gc.add(GregorianCalendar.HOUR_OF_DAY, hours);
return new DateAndTime(gc);
}
public DateAndTime addMinutes(int minutes) {
GregorianCalendar gc = toGregorianCalendar();
gc.add(GregorianCalendar.MINUTE, minutes);
return new DateAndTime(gc);
}
public Date getDate() {
return date;
}
public Time getTime() {
return time;
}
public GregorianCalendar toGregorianCalendar() {
GregorianCalendar gc = (GregorianCalendar) date.getGregorianCalendar().clone();
gc.add(GregorianCalendar.MILLISECOND, (int) time.toMillis());
return gc;
}
public java.util.Date toJavaDate() {
return toGregorianCalendar().getTime();
}
public long toMillis() {
return date.toMillis() + time.toMillis();
}
public TimePeriod getPeriodTo(DateAndTime other) {
return new TimePeriod(other.toMillis() - toMillis());
}
public TimePeriod getPeriodToNow() {
return getPeriodTo(now());
}
public String toString(DateFormat format) {
return format.format(toJavaDate());
}
public String toString(Locale locale) {
StringBuilder sb = new StringBuilder();
sb.append(date.toString(locale));
sb.append(", ");
sb.append(time.toString(locale));
return sb.toString();
}
public boolean isBefore(DateAndTime other) {
return compareTo(other) < 0;
}
public boolean isBeforeOrSame(DateAndTime other) {
return compareTo(other) <= 0;
}
public boolean isAfter(DateAndTime other) {
return compareTo(other) > 0;
}
public boolean isAfterOrSame(DateAndTime other) {
return compareTo(other) >= 0;
}
public boolean isFuture() {
return isAfter(now());
}
// --- static ---
public static DateAndTime now() {
GregorianCalendar gc = new GregorianCalendar();
return new DateAndTime(gc.get(GregorianCalendar.YEAR), gc.get(GregorianCalendar.MONTH) + 1,
gc.get(GregorianCalendar.DAY_OF_MONTH), gc.get(GregorianCalendar.HOUR_OF_DAY),
gc.get(GregorianCalendar.MINUTE), gc.get(GregorianCalendar.SECOND));
}
public static DateAndTime parse(String s, DateFormat... formats) throws ParseException {
ParseException ex = null;
for (DateFormat format : formats) {
try {
return new DateAndTime(format.parse(s));
} catch (ParseException e) {
ex = e;
}
}
throw ex;
}
// --- object ---
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(date.toString());
sb.append(" ");
sb.append(time.toString());
return sb.toString();
}
private transient int hashCode;
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode = 23;
hashCode = hashCode * 37 + date.hashCode();
hashCode = hashCode * 37 + time.hashCode();
}
return hashCode;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
return date.equals(((DateAndTime) obj).date) && time.equals(((DateAndTime) obj).time);
}
public int compareTo(DateAndTime o) {
int i = date.compareTo(o.date);
if (i == 0) { return time.compareTo(o.time); }
return i;
}
}