mirror of https://github.com/tasks/tasks
Use kotlinx.datetime
parent
b990716502
commit
bf4167651b
@ -1,440 +0,0 @@
|
||||
package org.tasks.time;
|
||||
|
||||
import static org.tasks.time.DateTimeUtils2.currentTimeMillis;
|
||||
import static java.util.Calendar.FRIDAY;
|
||||
import static java.util.Calendar.MONDAY;
|
||||
import static java.util.Calendar.SATURDAY;
|
||||
import static java.util.Calendar.SUNDAY;
|
||||
import static java.util.Calendar.THURSDAY;
|
||||
import static java.util.Calendar.TUESDAY;
|
||||
import static java.util.Calendar.WEDNESDAY;
|
||||
|
||||
import net.fortuna.ical4j.model.WeekDay;
|
||||
|
||||
import org.tasks.data.dao.CaldavDao;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DateTime {
|
||||
|
||||
public static final int MAX_MILLIS_PER_DAY = (int) TimeUnit.DAYS.toMillis(1) - 1;
|
||||
public static final TimeZone UTC = TimeZone.getTimeZone("GMT");
|
||||
private static final int MILLIS_PER_HOUR = (int) TimeUnit.HOURS.toMillis(1);
|
||||
private static final int MILLIS_PER_MINUTE = (int) TimeUnit.MINUTES.toMillis(1);
|
||||
private static final int MILLIS_PER_SECOND = (int) TimeUnit.SECONDS.toMillis(1);
|
||||
|
||||
private final TimeZone timeZone;
|
||||
private final long timestamp;
|
||||
|
||||
public DateTime(int year, int month, int day) {
|
||||
this(year, month, day, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public DateTime(int year, int month, int day, int hour, int minute) {
|
||||
this(year, month, day, hour, minute, 0, 0);
|
||||
}
|
||||
|
||||
public DateTime(int year, int month, int day, int hour, int minute, int second) {
|
||||
this(year, month, day, hour, minute, second, 0);
|
||||
}
|
||||
|
||||
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) {
|
||||
this(year, month, day, hour, minute, second, millisecond, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
public DateTime(
|
||||
int year,
|
||||
int month,
|
||||
int day,
|
||||
int hour,
|
||||
int minute,
|
||||
int second,
|
||||
int millisecond,
|
||||
TimeZone timeZone) {
|
||||
GregorianCalendar gregorianCalendar = new GregorianCalendar(timeZone);
|
||||
gregorianCalendar.set(year, month - 1, day, hour, minute, second);
|
||||
gregorianCalendar.set(Calendar.MILLISECOND, millisecond);
|
||||
timestamp = gregorianCalendar.getTimeInMillis();
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
public DateTime() {
|
||||
this(currentTimeMillis());
|
||||
}
|
||||
|
||||
public DateTime(long timestamp) {
|
||||
this(timestamp, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
public DateTime(long timestamp, TimeZone timeZone) {
|
||||
this.timestamp = timestamp;
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
private DateTime(Calendar calendar) {
|
||||
this(calendar.getTimeInMillis(), calendar.getTimeZone());
|
||||
}
|
||||
|
||||
public static DateTime from(Date date) {
|
||||
if (date == null) {
|
||||
return new DateTime(0);
|
||||
}
|
||||
DateTime dateTime = new DateTime(date.getTime());
|
||||
return dateTime.minusMillis(dateTime.getOffset());
|
||||
}
|
||||
|
||||
public static DateTime from(net.fortuna.ical4j.model.Date date) {
|
||||
if (date instanceof net.fortuna.ical4j.model.DateTime) {
|
||||
net.fortuna.ical4j.model.DateTime dt = (net.fortuna.ical4j.model.DateTime) date;
|
||||
TimeZone tz = dt.getTimeZone();
|
||||
return new DateTime(
|
||||
dt.getTime(),
|
||||
tz != null ? tz : dt.isUtc() ? UTC : TimeZone.getDefault()
|
||||
);
|
||||
} else {
|
||||
return from((java.util.Date) date);
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime setTime(int hours, int minutes, int seconds, int milliseconds) {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hours);
|
||||
calendar.set(Calendar.MINUTE, minutes);
|
||||
calendar.set(Calendar.SECOND, seconds);
|
||||
calendar.set(Calendar.MILLISECOND, milliseconds);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime startOfDay() {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime startOfMinute() {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime startOfSecond() {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime endOfMinute() {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.SECOND, 59);
|
||||
calendar.set(Calendar.MILLISECOND, 999);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime noon() {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 12);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime endOfDay() {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
||||
calendar.set(Calendar.MINUTE, 59);
|
||||
calendar.set(Calendar.SECOND, 59);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
public DateTime withMillisOfDay(int millisOfDay) {
|
||||
if (millisOfDay > MAX_MILLIS_PER_DAY || millisOfDay < 0) {
|
||||
throw new RuntimeException("Illegal millis of day: " + millisOfDay);
|
||||
}
|
||||
int hours = millisOfDay / MILLIS_PER_HOUR;
|
||||
millisOfDay %= MILLIS_PER_HOUR;
|
||||
int minutes = millisOfDay / MILLIS_PER_MINUTE;
|
||||
millisOfDay %= MILLIS_PER_MINUTE;
|
||||
int seconds = millisOfDay / MILLIS_PER_SECOND;
|
||||
millisOfDay %= MILLIS_PER_SECOND;
|
||||
return startOfDay().setTime(hours, minutes, seconds, millisOfDay);
|
||||
}
|
||||
|
||||
public long getOffset() {
|
||||
return timeZone.getOffset(timestamp);
|
||||
}
|
||||
|
||||
public long getMillis() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public int getMillisOfDay() {
|
||||
Calendar calendar = getCalendar();
|
||||
long millisOfDay =
|
||||
calendar.get(Calendar.MILLISECOND)
|
||||
+ TimeUnit.SECONDS.toMillis(calendar.get(Calendar.SECOND))
|
||||
+ TimeUnit.MINUTES.toMillis(calendar.get(Calendar.MINUTE))
|
||||
+ TimeUnit.HOURS.toMillis(calendar.get(Calendar.HOUR_OF_DAY));
|
||||
return (int) millisOfDay;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return getCalendar().get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
public int getMonthOfYear() {
|
||||
return getCalendar().get(Calendar.MONTH) + 1;
|
||||
}
|
||||
|
||||
public int getDayOfMonth() {
|
||||
return getCalendar().get(Calendar.DATE);
|
||||
}
|
||||
|
||||
public int getDayOfWeek() {
|
||||
return getCalendar().get(Calendar.DAY_OF_WEEK);
|
||||
}
|
||||
|
||||
public int getHourOfDay() {
|
||||
return getCalendar().get(Calendar.HOUR_OF_DAY);
|
||||
}
|
||||
|
||||
public int getMinuteOfHour() {
|
||||
return getCalendar().get(Calendar.MINUTE);
|
||||
}
|
||||
|
||||
public int getSecondOfMinute() {
|
||||
return getCalendar().get(Calendar.SECOND);
|
||||
}
|
||||
|
||||
public DateTime withYear(int year) {
|
||||
return with(Calendar.YEAR, year);
|
||||
}
|
||||
|
||||
public DateTime withMonthOfYear(int monthOfYear) {
|
||||
return with(Calendar.MONTH, monthOfYear - 1);
|
||||
}
|
||||
|
||||
public DateTime withDayOfMonth(int dayOfMonth) {
|
||||
return with(Calendar.DAY_OF_MONTH, dayOfMonth);
|
||||
}
|
||||
|
||||
public DateTime withHourOfDay(int hourOfDay) {
|
||||
return with(Calendar.HOUR_OF_DAY, hourOfDay);
|
||||
}
|
||||
|
||||
public DateTime withMinuteOfHour(int minuteOfHour) {
|
||||
return with(Calendar.MINUTE, minuteOfHour);
|
||||
}
|
||||
|
||||
public DateTime withSecondOfMinute(int secondOfMinute) {
|
||||
return with(Calendar.SECOND, secondOfMinute);
|
||||
}
|
||||
|
||||
public DateTime withMillisOfSecond(int millisOfSecond) {
|
||||
return with(Calendar.MILLISECOND, millisOfSecond);
|
||||
}
|
||||
|
||||
public DateTime plusMonths(int interval) {
|
||||
return add(Calendar.MONTH, interval);
|
||||
}
|
||||
|
||||
public DateTime plusWeeks(int weeks) {
|
||||
return add(Calendar.WEEK_OF_MONTH, weeks);
|
||||
}
|
||||
|
||||
public DateTime plusDays(int interval) {
|
||||
return add(Calendar.DATE, interval);
|
||||
}
|
||||
|
||||
public DateTime plusHours(int hours) {
|
||||
return add(Calendar.HOUR_OF_DAY, hours);
|
||||
}
|
||||
|
||||
public DateTime plusMinutes(int minutes) {
|
||||
return add(Calendar.MINUTE, minutes);
|
||||
}
|
||||
|
||||
public DateTime plusSeconds(int seconds) {
|
||||
return add(Calendar.SECOND, seconds);
|
||||
}
|
||||
|
||||
public DateTime plusMillis(int millis) {
|
||||
return add(Calendar.MILLISECOND, millis);
|
||||
}
|
||||
|
||||
public DateTime minusSeconds(int seconds) {
|
||||
return subtract(Calendar.SECOND, seconds);
|
||||
}
|
||||
|
||||
public DateTime minusDays(int days) {
|
||||
return subtract(Calendar.DATE, days);
|
||||
}
|
||||
|
||||
public DateTime minusMinutes(int minutes) {
|
||||
return subtract(Calendar.MINUTE, minutes);
|
||||
}
|
||||
|
||||
public DateTime minusMillis(long millis) {
|
||||
return new DateTime(timestamp - millis, timeZone);
|
||||
}
|
||||
|
||||
public boolean isAfterNow() {
|
||||
return isAfter(currentTimeMillis());
|
||||
}
|
||||
|
||||
public boolean isAfter(DateTime dateTime) {
|
||||
return isAfter(dateTime.getMillis());
|
||||
}
|
||||
|
||||
private boolean isAfter(long timestamp) {
|
||||
return this.timestamp > timestamp;
|
||||
}
|
||||
|
||||
public boolean isBeforeNow() {
|
||||
return timestamp < currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean isBefore(DateTime dateTime) {
|
||||
return timestamp < dateTime.getMillis();
|
||||
}
|
||||
|
||||
public DateTime toUTC() {
|
||||
return toTimeZone(UTC);
|
||||
}
|
||||
|
||||
public DateTime toLocal() {
|
||||
return toTimeZone(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
public boolean isLastDayOfMonth() {
|
||||
return getDayOfMonth() == getNumberOfDaysInMonth();
|
||||
}
|
||||
|
||||
public int getNumberOfDaysInMonth() {
|
||||
return getCalendar().getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
private DateTime toTimeZone(TimeZone timeZone) {
|
||||
if (timeZone == this.timeZone) {
|
||||
return this;
|
||||
}
|
||||
Calendar current = getCalendar();
|
||||
Calendar target = new GregorianCalendar(timeZone);
|
||||
target.setTimeInMillis(current.getTimeInMillis());
|
||||
return new DateTime(target);
|
||||
}
|
||||
|
||||
private DateTime with(int field, int value) {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.set(field, value);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
private DateTime subtract(int field, int value) {
|
||||
return add(field, -value);
|
||||
}
|
||||
|
||||
private DateTime add(int field, int value) {
|
||||
Calendar calendar = getCalendar();
|
||||
calendar.add(field, value);
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
private Calendar getCalendar() {
|
||||
Calendar calendar = new GregorianCalendar(timeZone);
|
||||
calendar.setTimeInMillis(timestamp);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public net.fortuna.ical4j.model.DateTime toDateTime() {
|
||||
return timestamp == 0 ? null : new net.fortuna.ical4j.model.DateTime(timestamp);
|
||||
}
|
||||
|
||||
public net.fortuna.ical4j.model.Date toDate() {
|
||||
return timestamp == 0 ? null : new net.fortuna.ical4j.model.Date(timestamp + getOffset());
|
||||
}
|
||||
|
||||
public LocalDate toLocalDate() {
|
||||
return timestamp == 0 ? null : LocalDate.of(getYear(), getMonthOfYear(), getDayOfMonth());
|
||||
}
|
||||
|
||||
public LocalDateTime toLocalDateTime() {
|
||||
return timestamp == 0 ? null : LocalDateTime.of(getYear(), getMonthOfYear(), getDayOfMonth(), getHourOfDay(), getMinuteOfHour());
|
||||
}
|
||||
|
||||
public long toAppleEpoch() {
|
||||
return CaldavDao.toAppleEpoch(timestamp);
|
||||
}
|
||||
|
||||
public int getDayOfWeekInMonth() {
|
||||
return getCalendar().get(Calendar.DAY_OF_WEEK_IN_MONTH);
|
||||
}
|
||||
|
||||
public int getMaxDayOfWeekInMonth() {
|
||||
return getCalendar().getActualMaximum(Calendar.DAY_OF_WEEK_IN_MONTH);
|
||||
}
|
||||
|
||||
public WeekDay getWeekDay() {
|
||||
switch (getCalendar().get(Calendar.DAY_OF_WEEK)) {
|
||||
case SUNDAY:
|
||||
return WeekDay.SU;
|
||||
case MONDAY:
|
||||
return WeekDay.MO;
|
||||
case TUESDAY:
|
||||
return WeekDay.TU;
|
||||
case WEDNESDAY:
|
||||
return WeekDay.WE;
|
||||
case THURSDAY:
|
||||
return WeekDay.TH;
|
||||
case FRIDAY:
|
||||
return WeekDay.FR;
|
||||
case SATURDAY:
|
||||
return WeekDay.SA;
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof DateTime)) {
|
||||
return false;
|
||||
}
|
||||
DateTime dateTime = (DateTime) o;
|
||||
return timestamp == dateTime.timestamp && Objects.equals(timeZone, dateTime.timeZone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(timeZone, timestamp);
|
||||
}
|
||||
|
||||
public String toString(String format) {
|
||||
Calendar calendar = getCalendar();
|
||||
SimpleDateFormat simpleDateFormat =
|
||||
new SimpleDateFormat(format, Locale.getDefault());
|
||||
simpleDateFormat.setCalendar(calendar);
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
}
|
||||
}
|
@ -0,0 +1,323 @@
|
||||
package org.tasks.time
|
||||
|
||||
import net.fortuna.ical4j.model.Date
|
||||
import net.fortuna.ical4j.model.WeekDay
|
||||
import org.tasks.data.dao.CaldavDao.Companion.toAppleEpoch
|
||||
import org.tasks.time.DateTimeUtils2.currentTimeMillis
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.util.Calendar
|
||||
import java.util.GregorianCalendar
|
||||
import java.util.Locale
|
||||
import java.util.Objects
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class DateTime {
|
||||
private val timeZone: TimeZone
|
||||
val millis: Long
|
||||
|
||||
@JvmOverloads
|
||||
constructor(
|
||||
year: Int,
|
||||
month: Int,
|
||||
day: Int,
|
||||
hour: Int = 0,
|
||||
minute: Int = 0,
|
||||
second: Int = 0,
|
||||
millisecond: Int = 0,
|
||||
timeZone: TimeZone = TimeZone.getDefault()
|
||||
) {
|
||||
val gregorianCalendar = GregorianCalendar(timeZone)
|
||||
gregorianCalendar[year, month - 1, day, hour, minute] = second
|
||||
gregorianCalendar[Calendar.MILLISECOND] = millisecond
|
||||
millis = gregorianCalendar.timeInMillis
|
||||
this.timeZone = timeZone
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
constructor(timestamp: Long = currentTimeMillis(), timeZone: TimeZone = TimeZone.getDefault()) {
|
||||
this.millis = timestamp
|
||||
this.timeZone = timeZone
|
||||
}
|
||||
|
||||
private constructor(calendar: Calendar) : this(calendar.timeInMillis, calendar.timeZone)
|
||||
|
||||
fun startOfDay(): DateTime = DateTime(millis.startOfDay())
|
||||
|
||||
fun startOfMinute(): DateTime = DateTime(millis.startOfMinute())
|
||||
|
||||
fun startOfSecond(): DateTime = DateTime(millis.startOfSecond())
|
||||
|
||||
fun endOfMinute(): DateTime = DateTime(millis.endOfMinute())
|
||||
|
||||
fun noon(): DateTime = DateTime(millis.noon())
|
||||
|
||||
fun endOfDay(): DateTime = DateTime(millis.endOfDay())
|
||||
|
||||
fun withMillisOfDay(millisOfDay: Int): DateTime = DateTime(millis.withMillisOfDay(millisOfDay))
|
||||
|
||||
val offset: Long
|
||||
get() = timeZone.getOffset(millis).toLong()
|
||||
|
||||
val millisOfDay: Int
|
||||
get() = millis.millisOfDay
|
||||
|
||||
val year: Int
|
||||
get() = calendar[Calendar.YEAR]
|
||||
|
||||
val monthOfYear: Int
|
||||
get() = calendar[Calendar.MONTH] + 1
|
||||
|
||||
val dayOfMonth: Int
|
||||
get() = calendar[Calendar.DATE]
|
||||
|
||||
val dayOfWeek: Int
|
||||
get() = calendar[Calendar.DAY_OF_WEEK]
|
||||
|
||||
val hourOfDay: Int
|
||||
get() = calendar[Calendar.HOUR_OF_DAY]
|
||||
|
||||
val minuteOfHour: Int
|
||||
get() = calendar[Calendar.MINUTE]
|
||||
|
||||
val secondOfMinute: Int
|
||||
get() = calendar[Calendar.SECOND]
|
||||
|
||||
fun withYear(year: Int): DateTime {
|
||||
return with(Calendar.YEAR, year)
|
||||
}
|
||||
|
||||
fun withMonthOfYear(monthOfYear: Int): DateTime {
|
||||
return with(Calendar.MONTH, monthOfYear - 1)
|
||||
}
|
||||
|
||||
fun withDayOfMonth(dayOfMonth: Int): DateTime {
|
||||
return with(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||
}
|
||||
|
||||
fun withHourOfDay(hourOfDay: Int): DateTime {
|
||||
return with(Calendar.HOUR_OF_DAY, hourOfDay)
|
||||
}
|
||||
|
||||
fun withMinuteOfHour(minuteOfHour: Int): DateTime {
|
||||
return with(Calendar.MINUTE, minuteOfHour)
|
||||
}
|
||||
|
||||
fun withSecondOfMinute(secondOfMinute: Int): DateTime {
|
||||
return with(Calendar.SECOND, secondOfMinute)
|
||||
}
|
||||
|
||||
fun withMillisOfSecond(millisOfSecond: Int): DateTime {
|
||||
return with(Calendar.MILLISECOND, millisOfSecond)
|
||||
}
|
||||
|
||||
fun plusMonths(interval: Int): DateTime {
|
||||
return add(Calendar.MONTH, interval)
|
||||
}
|
||||
|
||||
fun plusWeeks(weeks: Int): DateTime {
|
||||
return add(Calendar.WEEK_OF_MONTH, weeks)
|
||||
}
|
||||
|
||||
fun plusDays(interval: Int): DateTime {
|
||||
return add(Calendar.DATE, interval)
|
||||
}
|
||||
|
||||
fun plusHours(hours: Int): DateTime {
|
||||
return add(Calendar.HOUR_OF_DAY, hours)
|
||||
}
|
||||
|
||||
fun plusMinutes(minutes: Int): DateTime {
|
||||
return add(Calendar.MINUTE, minutes)
|
||||
}
|
||||
|
||||
fun plusSeconds(seconds: Int): DateTime {
|
||||
return add(Calendar.SECOND, seconds)
|
||||
}
|
||||
|
||||
fun plusMillis(millis: Int): DateTime {
|
||||
return add(Calendar.MILLISECOND, millis)
|
||||
}
|
||||
|
||||
fun minusSeconds(seconds: Int): DateTime {
|
||||
return subtract(Calendar.SECOND, seconds)
|
||||
}
|
||||
|
||||
fun minusDays(days: Int): DateTime {
|
||||
return subtract(Calendar.DATE, days)
|
||||
}
|
||||
|
||||
fun minusMinutes(minutes: Int): DateTime {
|
||||
return subtract(Calendar.MINUTE, minutes)
|
||||
}
|
||||
|
||||
fun minusMillis(millis: Long): DateTime {
|
||||
return DateTime(this.millis - millis, timeZone)
|
||||
}
|
||||
|
||||
val isAfterNow: Boolean
|
||||
get() = isAfter(currentTimeMillis())
|
||||
|
||||
fun isAfter(dateTime: DateTime): Boolean {
|
||||
return isAfter(dateTime.millis)
|
||||
}
|
||||
|
||||
private fun isAfter(timestamp: Long): Boolean {
|
||||
return this.millis > timestamp
|
||||
}
|
||||
|
||||
val isBeforeNow: Boolean
|
||||
get() = millis < currentTimeMillis()
|
||||
|
||||
fun isBefore(dateTime: DateTime): Boolean {
|
||||
return millis < dateTime.millis
|
||||
}
|
||||
|
||||
fun toUTC(): DateTime {
|
||||
return toTimeZone(UTC)
|
||||
}
|
||||
|
||||
fun toLocal(): DateTime {
|
||||
return toTimeZone(TimeZone.getDefault())
|
||||
}
|
||||
|
||||
val isLastDayOfMonth: Boolean
|
||||
get() = dayOfMonth == numberOfDaysInMonth
|
||||
|
||||
val numberOfDaysInMonth: Int
|
||||
get() = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
|
||||
|
||||
private fun toTimeZone(timeZone: TimeZone): DateTime {
|
||||
if (timeZone === this.timeZone) {
|
||||
return this
|
||||
}
|
||||
val current = calendar
|
||||
val target: Calendar = GregorianCalendar(timeZone)
|
||||
target.timeInMillis = current.timeInMillis
|
||||
return DateTime(target)
|
||||
}
|
||||
|
||||
private fun with(field: Int, value: Int): DateTime {
|
||||
val calendar = calendar
|
||||
calendar[field] = value
|
||||
return DateTime(calendar)
|
||||
}
|
||||
|
||||
private fun subtract(field: Int, value: Int): DateTime {
|
||||
return add(field, -value)
|
||||
}
|
||||
|
||||
private fun add(field: Int, value: Int): DateTime {
|
||||
val calendar = calendar
|
||||
calendar.add(field, value)
|
||||
return DateTime(calendar)
|
||||
}
|
||||
|
||||
private val calendar: Calendar
|
||||
get() {
|
||||
val calendar: Calendar = GregorianCalendar(timeZone)
|
||||
calendar.timeInMillis = millis
|
||||
return calendar
|
||||
}
|
||||
|
||||
fun toDateTime(): net.fortuna.ical4j.model.DateTime {
|
||||
return if (millis == 0L) throw IllegalStateException() else net.fortuna.ical4j.model.DateTime(millis)
|
||||
}
|
||||
|
||||
fun toDate(): Date {
|
||||
return if (millis == 0L) throw IllegalStateException() else Date(millis + offset)
|
||||
}
|
||||
|
||||
fun toLocalDate(): LocalDate? {
|
||||
return if (millis == 0L) null else LocalDate.of(year, monthOfYear, dayOfMonth)
|
||||
}
|
||||
|
||||
fun toLocalDateTime(): LocalDateTime? {
|
||||
return if (millis == 0L) null else LocalDateTime.of(
|
||||
year,
|
||||
monthOfYear,
|
||||
dayOfMonth,
|
||||
hourOfDay,
|
||||
minuteOfHour
|
||||
)
|
||||
}
|
||||
|
||||
fun toAppleEpoch(): Long {
|
||||
return millis.toAppleEpoch()
|
||||
}
|
||||
|
||||
val dayOfWeekInMonth: Int
|
||||
get() = calendar[Calendar.DAY_OF_WEEK_IN_MONTH]
|
||||
|
||||
val maxDayOfWeekInMonth: Int
|
||||
get() = calendar.getActualMaximum(Calendar.DAY_OF_WEEK_IN_MONTH)
|
||||
|
||||
val weekDay: WeekDay
|
||||
get() {
|
||||
when (calendar[Calendar.DAY_OF_WEEK]) {
|
||||
Calendar.SUNDAY -> return WeekDay.SU
|
||||
Calendar.MONDAY -> return WeekDay.MO
|
||||
Calendar.TUESDAY -> return WeekDay.TU
|
||||
Calendar.WEDNESDAY -> return WeekDay.WE
|
||||
Calendar.THURSDAY -> return WeekDay.TH
|
||||
Calendar.FRIDAY -> return WeekDay.FR
|
||||
Calendar.SATURDAY -> return WeekDay.SA
|
||||
}
|
||||
throw RuntimeException()
|
||||
}
|
||||
|
||||
override fun equals(o: Any?): Boolean {
|
||||
if (this === o) {
|
||||
return true
|
||||
}
|
||||
if (o !is DateTime) {
|
||||
return false
|
||||
}
|
||||
val dateTime = o
|
||||
return millis == dateTime.millis && timeZone == dateTime.timeZone
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Objects.hash(timeZone, millis)
|
||||
}
|
||||
|
||||
fun toString(format: String?): String {
|
||||
val calendar = calendar
|
||||
val simpleDateFormat =
|
||||
SimpleDateFormat(format, Locale.getDefault())
|
||||
simpleDateFormat.calendar = calendar
|
||||
return simpleDateFormat.format(calendar.time)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return toString("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
|
||||
}
|
||||
|
||||
companion object {
|
||||
val MAX_MILLIS_PER_DAY: Int = TimeUnit.DAYS.toMillis(1).toInt() - 1
|
||||
val UTC: TimeZone = TimeZone.getTimeZone("GMT")
|
||||
|
||||
fun from(date: java.util.Date?): DateTime {
|
||||
if (date == null) {
|
||||
return DateTime(0)
|
||||
}
|
||||
val dateTime = DateTime(date.time)
|
||||
return dateTime.minusMillis(dateTime.offset)
|
||||
}
|
||||
|
||||
fun from(date: Date?): DateTime {
|
||||
if (date is net.fortuna.ical4j.model.DateTime) {
|
||||
val dt = date
|
||||
val tz: TimeZone? = dt.timeZone
|
||||
return DateTime(
|
||||
dt.time,
|
||||
tz ?: if (dt.isUtc) UTC else TimeZone.getDefault()
|
||||
)
|
||||
} else {
|
||||
return from(date as java.util.Date?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package org.tasks.time
|
||||
|
||||
import kotlinx.datetime.Clock
|
||||
|
||||
class SystemMillisProvider : MillisProvider {
|
||||
override val millis: Long
|
||||
get() = System.currentTimeMillis()
|
||||
get() = Clock.System.now().toEpochMilliseconds()
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
package org.tasks.time
|
||||
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.LocalTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toInstant
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
|
||||
fun Long.noon(): Long =
|
||||
if (this > 0) {
|
||||
toLocalDateTime()
|
||||
.let { LocalDateTime(it.year, it.month, it.dayOfMonth, 12, 0, 0, 0) }
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
fun Long.startOfDay(): Long =
|
||||
if (this > 0) {
|
||||
toLocalDateTime()
|
||||
.let { LocalDateTime(it.year, it.month, it.dayOfMonth, 0, 0, 0, 0) }
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
fun Long.startOfMinute(): Long =
|
||||
if (this > 0) {
|
||||
toLocalDateTime()
|
||||
.let { LocalDateTime(it.year, it.month, it.dayOfMonth, it.hour, it.minute, 0, 0) }
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
fun Long.startOfSecond(): Long =
|
||||
if (this > 0) {
|
||||
toLocalDateTime()
|
||||
.let {
|
||||
LocalDateTime(
|
||||
it.year,
|
||||
it.month,
|
||||
it.dayOfMonth,
|
||||
it.hour,
|
||||
it.minute,
|
||||
it.second,
|
||||
0
|
||||
)
|
||||
}
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
fun Long.endOfMinute(): Long =
|
||||
if (this > 0) {
|
||||
toLocalDateTime()
|
||||
.let {
|
||||
LocalDateTime(
|
||||
it.year,
|
||||
it.month,
|
||||
it.dayOfMonth,
|
||||
it.hour,
|
||||
it.minute,
|
||||
59,
|
||||
999_000_000
|
||||
)
|
||||
}
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
fun Long.endOfDay(): Long =
|
||||
if (this > 0) {
|
||||
toLocalDateTime()
|
||||
.let { LocalDateTime(it.year, it.month, it.dayOfMonth, 23, 59, 59, 0) }
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
fun Long.withMillisOfDay(millisOfDay: Int): Long =
|
||||
if (this > 0) {
|
||||
LocalDateTime(
|
||||
date = toLocalDateTime().date,
|
||||
time = LocalTime.fromMillisecondOfDay(millisOfDay)
|
||||
)
|
||||
.toEpochMilliseconds()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val Long.millisOfDay: Int
|
||||
get() = if (this > 0) toLocalDateTime().time.toMillisecondOfDay() else 0
|
||||
|
||||
private fun Long.toLocalDateTime(): LocalDateTime =
|
||||
Instant.fromEpochMilliseconds(this).toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
|
||||
private fun LocalDateTime.toEpochMilliseconds(): Long =
|
||||
toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
Loading…
Reference in New Issue