mirror of https://github.com/iSoron/uhabits.git
commit
d279388884
@ -1,333 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.utils;
|
||||
|
||||
import androidx.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Calendar.*;
|
||||
|
||||
public abstract class DateUtils
|
||||
{
|
||||
|
||||
private static Long fixedLocalTime = null;
|
||||
|
||||
private static TimeZone fixedTimeZone = null;
|
||||
|
||||
private static Locale fixedLocale = null;
|
||||
|
||||
private static int startDayHourOffset = 0;
|
||||
|
||||
private static int startDayMinuteOffset = 0;
|
||||
|
||||
/**
|
||||
* Number of milliseconds in one minute.
|
||||
*/
|
||||
|
||||
public static final long MINUTE_LENGTH = 60 * 1000;
|
||||
|
||||
/**
|
||||
* Number of milliseconds in one hour.
|
||||
*/
|
||||
public static final long HOUR_LENGTH = 60 * MINUTE_LENGTH;
|
||||
|
||||
/**
|
||||
* Number of milliseconds in one day.
|
||||
*/
|
||||
public static final long DAY_LENGTH = 24 * HOUR_LENGTH;
|
||||
|
||||
public static long applyTimezone(long localTimestamp)
|
||||
{
|
||||
TimeZone tz = getTimezone();
|
||||
return localTimestamp - tz.getOffset(localTimestamp - tz.getOffset(localTimestamp));
|
||||
}
|
||||
|
||||
public static String formatHeaderDate(GregorianCalendar day)
|
||||
{
|
||||
Locale locale = getLocale();
|
||||
String dayOfMonth = Integer.toString(day.get(DAY_OF_MONTH));
|
||||
String dayOfWeek = day.getDisplayName(DAY_OF_WEEK, SHORT, locale);
|
||||
return dayOfWeek + "\n" + dayOfMonth;
|
||||
}
|
||||
|
||||
private static GregorianCalendar getCalendar(long timestamp)
|
||||
{
|
||||
GregorianCalendar day =
|
||||
new GregorianCalendar(TimeZone.getTimeZone("GMT"), getLocale());
|
||||
day.setTimeInMillis(timestamp);
|
||||
return day;
|
||||
}
|
||||
|
||||
public static long getLocalTime()
|
||||
{
|
||||
if (fixedLocalTime != null) return fixedLocalTime;
|
||||
|
||||
TimeZone tz = getTimezone();
|
||||
long now = new Date().getTime();
|
||||
return now + tz.getOffset(now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of strings with the names for each day of the week,
|
||||
* in either SHORT or LONG format. The first entry corresponds to the
|
||||
* first day of the week, according to the provided argument.
|
||||
*
|
||||
* @param format Either GregorianCalendar.SHORT or LONG
|
||||
* @param firstWeekday An integer representing the first day of the week,
|
||||
* following java.util.Calendar conventions. That is,
|
||||
* Saturday corresponds to 7, and Sunday corresponds
|
||||
* to 1.
|
||||
*/
|
||||
@NotNull
|
||||
private static String[] getWeekdayNames(int format, int firstWeekday)
|
||||
{
|
||||
String[] days = new String[7];
|
||||
Calendar calendar = new GregorianCalendar();
|
||||
calendar.set(DAY_OF_WEEK, firstWeekday);
|
||||
for (int i = 0; i < days.length; i++) {
|
||||
days[i] = calendar.getDisplayName(DAY_OF_WEEK, format,
|
||||
getLocale());
|
||||
calendar.add(DAY_OF_MONTH, 1);
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector of exactly seven integers, where the first integer is
|
||||
* the provided firstWeekday number, and each subsequent number is the
|
||||
* previous number plus 1, wrapping back to 1 after 7. For example,
|
||||
* providing 3 as firstWeekday returns {3,4,5,6,7,1,2}
|
||||
*
|
||||
* This function is supposed to be used to construct a sequence of weekday
|
||||
* number following java.util.Calendar conventions.
|
||||
*/
|
||||
public static int[] getWeekdaySequence(int firstWeekday)
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
(firstWeekday - 1) % 7 + 1,
|
||||
(firstWeekday) % 7 + 1,
|
||||
(firstWeekday + 1) % 7 + 1,
|
||||
(firstWeekday + 2) % 7 + 1,
|
||||
(firstWeekday + 3) % 7 + 1,
|
||||
(firstWeekday + 4) % 7 + 1,
|
||||
(firstWeekday + 5) % 7 + 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An integer representing the first day of the week, according to
|
||||
* the current locale. Sunday corresponds to 1, Monday to 2, and so on,
|
||||
* until Saturday, which is represented by 7. This is consistent
|
||||
* with java.util.Calendar constants.
|
||||
*/
|
||||
public static int getFirstWeekdayNumberAccordingToLocale()
|
||||
{
|
||||
return new GregorianCalendar().getFirstDayOfWeek();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector of strings with the long names for the week days,
|
||||
* according to the current locale. The first entry corresponds to Saturday,
|
||||
* the second entry corresponds to Monday, and so on.
|
||||
*
|
||||
* @param firstWeekday Either Calendar.SATURDAY, Calendar.MONDAY, or other
|
||||
* weekdays defined in this class.
|
||||
*/
|
||||
public static String[] getLongWeekdayNames(int firstWeekday)
|
||||
{
|
||||
return getWeekdayNames(GregorianCalendar.LONG, firstWeekday);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector of strings with the short names for the week days,
|
||||
* according to the current locale. The first entry corresponds to Saturday,
|
||||
* the second entry corresponds to Monday, and so on.
|
||||
*
|
||||
* @param firstWeekday Either Calendar.SATURDAY, Calendar.MONDAY, or other
|
||||
* weekdays defined in this class.
|
||||
*/
|
||||
public static String[] getShortWeekdayNames(int firstWeekday)
|
||||
{
|
||||
return getWeekdayNames(GregorianCalendar.SHORT, firstWeekday);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Timestamp getToday()
|
||||
{
|
||||
return new Timestamp(getStartOfToday());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Timestamp getTodayWithOffset()
|
||||
{
|
||||
return new Timestamp(getStartOfTodayWithOffset());
|
||||
}
|
||||
|
||||
public static long getStartOfDay(long timestamp)
|
||||
{
|
||||
return (timestamp / DAY_LENGTH) * DAY_LENGTH;
|
||||
}
|
||||
|
||||
public static long getStartOfDayWithOffset(long timestamp)
|
||||
{
|
||||
long offset = startDayHourOffset * HOUR_LENGTH + startDayMinuteOffset * MINUTE_LENGTH;
|
||||
return getStartOfDay(timestamp - offset);
|
||||
}
|
||||
|
||||
public static long getStartOfToday()
|
||||
{
|
||||
return getStartOfDay(getLocalTime());
|
||||
}
|
||||
|
||||
public static long getStartOfTomorrowWithOffset()
|
||||
{
|
||||
return getUpcomingTimeInMillis(startDayHourOffset, startDayMinuteOffset);
|
||||
}
|
||||
|
||||
public static long getStartOfTodayWithOffset()
|
||||
{
|
||||
return getStartOfDayWithOffset(getLocalTime());
|
||||
}
|
||||
|
||||
public static long millisecondsUntilTomorrowWithOffset()
|
||||
{
|
||||
return getStartOfTomorrowWithOffset() - getLocalTime();
|
||||
}
|
||||
|
||||
public static GregorianCalendar getStartOfTodayCalendar()
|
||||
{
|
||||
return getCalendar(getStartOfToday());
|
||||
}
|
||||
|
||||
public static GregorianCalendar getStartOfTodayCalendarWithOffset()
|
||||
{
|
||||
return getCalendar(getStartOfTodayWithOffset());
|
||||
}
|
||||
|
||||
private static TimeZone getTimezone()
|
||||
{
|
||||
if(fixedTimeZone != null) return fixedTimeZone;
|
||||
return TimeZone.getDefault();
|
||||
}
|
||||
|
||||
public static void setFixedTimeZone(TimeZone tz)
|
||||
{
|
||||
fixedTimeZone = tz;
|
||||
}
|
||||
|
||||
public static long removeTimezone(long timestamp)
|
||||
{
|
||||
TimeZone tz = getTimezone();
|
||||
return timestamp + tz.getOffset(timestamp);
|
||||
}
|
||||
|
||||
public static void setFixedLocalTime(Long timestamp)
|
||||
{
|
||||
fixedLocalTime = timestamp;
|
||||
}
|
||||
|
||||
public static void setFixedLocale(Locale locale)
|
||||
{
|
||||
fixedLocale = locale;
|
||||
}
|
||||
|
||||
public static void setStartDayOffset(int hourOffset, int minuteOffset)
|
||||
{
|
||||
startDayHourOffset = hourOffset;
|
||||
startDayMinuteOffset = minuteOffset;
|
||||
}
|
||||
|
||||
private static Locale getLocale()
|
||||
{
|
||||
if(fixedLocale != null) return fixedLocale;
|
||||
return Locale.getDefault();
|
||||
}
|
||||
|
||||
public static Timestamp truncate(TruncateField field,
|
||||
Timestamp timestamp,
|
||||
int firstWeekday)
|
||||
{
|
||||
return new Timestamp(truncate(field, timestamp.getUnixTime(), firstWeekday));
|
||||
}
|
||||
|
||||
public static Long truncate(TruncateField field,
|
||||
long timestamp,
|
||||
int firstWeekday)
|
||||
{
|
||||
GregorianCalendar cal = DateUtils.getCalendar(timestamp);
|
||||
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case DAY:
|
||||
return cal.getTimeInMillis();
|
||||
|
||||
case MONTH:
|
||||
cal.set(DAY_OF_MONTH, 1);
|
||||
return cal.getTimeInMillis();
|
||||
|
||||
case WEEK_NUMBER:
|
||||
int weekday = cal.get(DAY_OF_WEEK);
|
||||
int delta = weekday - firstWeekday;
|
||||
if (delta < 0) delta += 7;
|
||||
cal.add(Calendar.DAY_OF_YEAR, -delta);
|
||||
return cal.getTimeInMillis();
|
||||
|
||||
case QUARTER:
|
||||
int quarter = cal.get(Calendar.MONTH) / 3;
|
||||
cal.set(DAY_OF_MONTH, 1);
|
||||
cal.set(Calendar.MONTH, quarter * 3);
|
||||
return cal.getTimeInMillis();
|
||||
|
||||
case YEAR:
|
||||
cal.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
cal.set(DAY_OF_MONTH, 1);
|
||||
return cal.getTimeInMillis();
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public static long getUpcomingTimeInMillis(int hour, int minute)
|
||||
{
|
||||
Calendar calendar = DateUtils.getStartOfTodayCalendar();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
long time = calendar.getTimeInMillis();
|
||||
|
||||
if (DateUtils.getLocalTime() > time)
|
||||
time += DateUtils.DAY_LENGTH;
|
||||
|
||||
return applyTimezone(time);
|
||||
}
|
||||
|
||||
public enum TruncateField
|
||||
{
|
||||
DAY, MONTH, WEEK_NUMBER, YEAR, QUARTER
|
||||
}
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.isoron.uhabits.core.utils
|
||||
|
||||
import org.isoron.uhabits.core.models.Timestamp
|
||||
import java.util.Calendar
|
||||
import java.util.Calendar.DAY_OF_MONTH
|
||||
import java.util.Calendar.DAY_OF_WEEK
|
||||
import java.util.Calendar.SHORT
|
||||
import java.util.Date
|
||||
import java.util.GregorianCalendar
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
|
||||
abstract class DateUtils {
|
||||
companion object {
|
||||
private var fixedLocalTime: Long? = null
|
||||
private var fixedTimeZone: TimeZone? = null
|
||||
private var fixedLocale: Locale? = null
|
||||
private var startDayHourOffset: Int = 0
|
||||
private var startDayMinuteOffset: Int = 0
|
||||
|
||||
/**
|
||||
* Number of milliseconds in one minute.
|
||||
*/
|
||||
const val MINUTE_LENGTH: Long = 60 * 1000
|
||||
|
||||
/**
|
||||
* Number of milliseconds in one hour.
|
||||
*/
|
||||
const val HOUR_LENGTH: Long = 60 * MINUTE_LENGTH
|
||||
|
||||
/**
|
||||
* Number of milliseconds in one day.
|
||||
*/
|
||||
const val DAY_LENGTH: Long = 24 * HOUR_LENGTH
|
||||
|
||||
@JvmStatic
|
||||
fun applyTimezone(localTimestamp: Long): Long {
|
||||
val tz: TimeZone = getTimeZone()
|
||||
return localTimestamp - tz.getOffset(localTimestamp - tz.getOffset(localTimestamp))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun formatHeaderDate(day: GregorianCalendar): String {
|
||||
val locale = getLocale()
|
||||
val dayOfMonth: String = day.get(DAY_OF_MONTH).toString()
|
||||
val dayOfWeek = day.getDisplayName(DAY_OF_WEEK, SHORT, locale)
|
||||
return dayOfWeek + "\n" + dayOfMonth
|
||||
}
|
||||
|
||||
private fun getCalendar(timestamp: Long): GregorianCalendar {
|
||||
val day = GregorianCalendar(TimeZone.getTimeZone("GMT"), getLocale())
|
||||
day.timeInMillis = timestamp
|
||||
return day
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getLocalTime(): Long {
|
||||
if (fixedLocalTime != null) return fixedLocalTime as Long
|
||||
|
||||
val tz = getTimeZone()
|
||||
val now = Date().getTime()
|
||||
return now + tz.getOffset(now)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of strings with the names for each day of the week,
|
||||
* in either SHORT or LONG format. The first entry corresponds to the
|
||||
* first day of the week, according to the provided argument.
|
||||
*
|
||||
* @param format Either GregorianCalendar.SHORT or LONG
|
||||
* @param firstWeekDay An integer representing the first day of the week,
|
||||
* following java.util.Calendar conventions. That is,
|
||||
* Saturday corresponds to 7, and Sunday corresponds
|
||||
* to 1.
|
||||
*/
|
||||
private fun getWeekdayNames(
|
||||
format: Int,
|
||||
firstWeekDay: Int
|
||||
): Array<String> {
|
||||
val calendar = GregorianCalendar()
|
||||
calendar.set(DAY_OF_WEEK, firstWeekDay)
|
||||
|
||||
val daysNullable = ArrayList<String>()
|
||||
for (i in 1..7) {
|
||||
daysNullable.add(
|
||||
calendar.getDisplayName(
|
||||
DAY_OF_WEEK,
|
||||
format,
|
||||
getLocale()
|
||||
)
|
||||
)
|
||||
|
||||
calendar.add(DAY_OF_MONTH, 1)
|
||||
}
|
||||
|
||||
return daysNullable.toTypedArray()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector of exactly seven integers, where the first integer is
|
||||
* the provided firstWeekday number, and each subsequent number is the
|
||||
* previous number plus 1, wrapping back to 1 after 7. For example,
|
||||
* providing 3 as firstWeekday returns {3,4,5,6,7,1,2}
|
||||
*
|
||||
* This function is supposed to be used to construct a sequence of weekday
|
||||
* number following java.util.Calendar conventions.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getWeekdaySequence(firstWeekday: Int): Array<Int> {
|
||||
return arrayOf(
|
||||
(firstWeekday - 1) % 7 + 1,
|
||||
(firstWeekday) % 7 + 1,
|
||||
(firstWeekday + 1) % 7 + 1,
|
||||
(firstWeekday + 2) % 7 + 1,
|
||||
(firstWeekday + 3) % 7 + 1,
|
||||
(firstWeekday + 4) % 7 + 1,
|
||||
(firstWeekday + 5) % 7 + 1,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An integer representing the first day of the week, according to
|
||||
* the current locale. Sunday corresponds to 1, Monday to 2, and so on,
|
||||
* until Saturday, which is represented by 7. This is consistent
|
||||
* with java.util.Calendar constants.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getFirstWeekdayNumberAccordingToLocale(): Int {
|
||||
return GregorianCalendar().firstDayOfWeek
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector of strings with the long names for the week days,
|
||||
* according to the current locale. The first entry corresponds to Saturday,
|
||||
* the second entry corresponds to Monday, and so on.
|
||||
*
|
||||
* @param firstWeekday Either Calendar.SATURDAY, Calendar.MONDAY, or other
|
||||
* weekdays defined in this class.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getLongWeekdayNames(firstWeekday: Int): Array<String> {
|
||||
return getWeekdayNames(GregorianCalendar.LONG, firstWeekday)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vector of strings with the short names for the week days,
|
||||
* according to the current locale. The first entry corresponds to Saturday,
|
||||
* the second entry corresponds to Monday, and so on.
|
||||
*
|
||||
* @param firstWeekday Either Calendar.SATURDAY, Calendar.MONDAY, or other
|
||||
* weekdays defined in this class.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getShortWeekdayNames(firstWeekday: Int): Array<String> {
|
||||
return getWeekdayNames(GregorianCalendar.SHORT, firstWeekday)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getToday(): Timestamp = Timestamp(getStartOfToday())
|
||||
|
||||
@JvmStatic
|
||||
fun getTodayWithOffset(): Timestamp = Timestamp(getStartOfTodayWithOffset())
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfDay(timestamp: Long): Long = (timestamp / DAY_LENGTH) * DAY_LENGTH
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfDayWithOffset(timestamp: Long): Long {
|
||||
val offset = startDayHourOffset * HOUR_LENGTH + startDayMinuteOffset * MINUTE_LENGTH
|
||||
return getStartOfDay(timestamp - offset)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfToday(): Long = getStartOfDay(getLocalTime())
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfTomorrowWithOffset(): Long = getUpcomingTimeInMillis(
|
||||
startDayHourOffset,
|
||||
startDayMinuteOffset
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfTodayWithOffset(): Long = getStartOfDayWithOffset(getLocalTime())
|
||||
|
||||
@JvmStatic
|
||||
fun millisecondsUntilTomorrowWithOffset(): Long = getStartOfTomorrowWithOffset() - getLocalTime()
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfTodayCalendar(): GregorianCalendar = getCalendar(getStartOfToday())
|
||||
|
||||
@JvmStatic
|
||||
fun getStartOfTodayCalendarWithOffset(): GregorianCalendar = getCalendar(getStartOfTodayWithOffset())
|
||||
|
||||
@JvmStatic
|
||||
fun getTimeZone(): TimeZone {
|
||||
return fixedTimeZone ?: TimeZone.getDefault()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getTimezone(): TimeZone {
|
||||
return fixedTimeZone ?: TimeZone.getDefault()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeTimezone(timestamp: Long): Long {
|
||||
val tz = getTimeZone()
|
||||
return timestamp + tz.getOffset(timestamp)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setStartDayOffset(hourOffset: Int, minuteOffset: Int) {
|
||||
startDayHourOffset = hourOffset
|
||||
startDayMinuteOffset = minuteOffset
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getLocale(): Locale {
|
||||
return fixedLocale ?: Locale.getDefault()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun truncate(
|
||||
field: TruncateField,
|
||||
timestamp: Timestamp,
|
||||
firstWeekday: Int
|
||||
): Timestamp {
|
||||
return Timestamp(
|
||||
truncate(
|
||||
field,
|
||||
timestamp.unixTime,
|
||||
firstWeekday
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun truncate(
|
||||
field: TruncateField,
|
||||
timestamp: Long,
|
||||
firstWeekday: Int
|
||||
): Long {
|
||||
val cal = getCalendar(timestamp)
|
||||
|
||||
return when (field) {
|
||||
|
||||
TruncateField.DAY -> { cal.timeInMillis }
|
||||
|
||||
TruncateField.MONTH -> {
|
||||
cal.set(DAY_OF_MONTH, 1)
|
||||
cal.timeInMillis
|
||||
}
|
||||
|
||||
TruncateField.WEEK_NUMBER -> {
|
||||
val weekDay = cal.get(DAY_OF_WEEK)
|
||||
var delta = weekDay - firstWeekday
|
||||
if (delta < 0) { delta += 7 }
|
||||
cal.add(Calendar.DAY_OF_YEAR, -delta)
|
||||
cal.timeInMillis
|
||||
}
|
||||
|
||||
TruncateField.QUARTER -> {
|
||||
val quarter = cal.get(Calendar.MONTH) / 3
|
||||
cal.set(DAY_OF_MONTH, 1)
|
||||
cal.set(Calendar.MONTH, quarter * 3)
|
||||
cal.timeInMillis
|
||||
}
|
||||
|
||||
TruncateField.YEAR -> {
|
||||
cal.set(Calendar.MONTH, Calendar.JANUARY)
|
||||
cal.set(DAY_OF_MONTH, 1)
|
||||
cal.timeInMillis
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getUpcomingTimeInMillis(
|
||||
hour: Int,
|
||||
minute: Int
|
||||
): Long {
|
||||
val calendar = getStartOfTodayCalendar()
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour)
|
||||
calendar.set(Calendar.MINUTE, minute)
|
||||
calendar.set(Calendar.SECOND, 0)
|
||||
var time = calendar.timeInMillis
|
||||
|
||||
if (getLocalTime() > time) {
|
||||
time += DAY_LENGTH
|
||||
}
|
||||
|
||||
return applyTimezone(time)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setFixedLocalTime(newFixedLocalTime: Long?) {
|
||||
this.fixedLocalTime = newFixedLocalTime
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setFixedTimeZone(newTimeZone: TimeZone?) {
|
||||
this.fixedTimeZone = newTimeZone
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setFixedLocale(newLocale: Locale?) {
|
||||
this.fixedLocale = newLocale
|
||||
}
|
||||
}
|
||||
|
||||
enum class TruncateField {
|
||||
DAY, MONTH, WEEK_NUMBER, YEAR, QUARTER
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.utils;
|
||||
|
||||
import org.isoron.uhabits.core.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
/**
|
||||
* A class that emits events when a new day starts.
|
||||
*/
|
||||
@AppScope
|
||||
public class MidnightTimer
|
||||
{
|
||||
private final List<MidnightListener> listeners;
|
||||
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
@Inject
|
||||
public MidnightTimer()
|
||||
{
|
||||
this.listeners = new LinkedList<>();
|
||||
}
|
||||
|
||||
public synchronized void addListener(MidnightListener listener)
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public synchronized void onPause()
|
||||
{
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
public synchronized void onResume()
|
||||
{
|
||||
executor = Executors.newSingleThreadScheduledExecutor();
|
||||
executor.scheduleAtFixedRate(() -> notifyListeners(),
|
||||
DateUtils.millisecondsUntilTomorrowWithOffset() + 1000,
|
||||
DateUtils.DAY_LENGTH, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public synchronized void removeListener(MidnightListener listener)
|
||||
{
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
private synchronized void notifyListeners()
|
||||
{
|
||||
for (MidnightListener l : listeners) l.atMidnight();
|
||||
}
|
||||
|
||||
public interface MidnightListener
|
||||
{
|
||||
void atMidnight();
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.isoron.uhabits.core.utils
|
||||
|
||||
import org.isoron.uhabits.core.AppScope
|
||||
import java.util.LinkedList
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* A class that emits events when a new day starts.
|
||||
*/
|
||||
@AppScope
|
||||
open class MidnightTimer @Inject constructor() {
|
||||
private val listeners: MutableList<MidnightListener> = LinkedList()
|
||||
private lateinit var executor: ScheduledExecutorService
|
||||
|
||||
@Synchronized fun addListener(listener: MidnightListener) {
|
||||
this.listeners.add(listener)
|
||||
}
|
||||
|
||||
@Synchronized fun onPause() = executor.shutdownNow()
|
||||
|
||||
@Synchronized fun onResume() {
|
||||
executor = Executors.newSingleThreadScheduledExecutor()
|
||||
executor.scheduleAtFixedRate(
|
||||
{ notifyListeners() },
|
||||
DateUtils.millisecondsUntilTomorrowWithOffset() + 1000,
|
||||
DateUtils.DAY_LENGTH,
|
||||
TimeUnit.MILLISECONDS
|
||||
)
|
||||
}
|
||||
|
||||
@Synchronized fun removeListener(listener: MidnightListener) = this.listeners.remove(listener)
|
||||
|
||||
@Synchronized private fun notifyListeners() {
|
||||
for (l in listeners) {
|
||||
l.atMidnight()
|
||||
}
|
||||
}
|
||||
|
||||
interface MidnightListener {
|
||||
fun atMidnight()
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.utils;
|
||||
|
||||
import org.apache.commons.lang3.builder.*;
|
||||
|
||||
import java.math.*;
|
||||
import java.util.*;
|
||||
|
||||
public class StringUtils
|
||||
{
|
||||
private static StandardToStringStyle toStringStyle = null;
|
||||
|
||||
public static String getRandomId()
|
||||
{
|
||||
return new BigInteger(260, new Random()).toString(32).substring(0, 32);
|
||||
}
|
||||
|
||||
public static ToStringStyle defaultToStringStyle()
|
||||
{
|
||||
if (toStringStyle == null)
|
||||
{
|
||||
toStringStyle = new StandardToStringStyle();
|
||||
toStringStyle.setFieldSeparator(", ");
|
||||
toStringStyle.setUseClassName(false);
|
||||
toStringStyle.setUseIdentityHashCode(false);
|
||||
toStringStyle.setContentStart("{");
|
||||
toStringStyle.setContentEnd("}");
|
||||
toStringStyle.setFieldNameValueSeparator(": ");
|
||||
toStringStyle.setArrayStart("[");
|
||||
toStringStyle.setArrayEnd("]");
|
||||
}
|
||||
|
||||
return toStringStyle;
|
||||
}
|
||||
|
||||
public static String joinLongs(long values[])
|
||||
{
|
||||
return org.apache.commons.lang3.StringUtils.join(values, ',');
|
||||
}
|
||||
|
||||
public static long[] splitLongs(String str)
|
||||
{
|
||||
String parts[] = org.apache.commons.lang3.StringUtils.split(str, ',');
|
||||
|
||||
long numbers[] = new long[parts.length];
|
||||
for (int i = 0; i < parts.length; i++) numbers[i] = Long.valueOf(parts[i]);
|
||||
return numbers;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.core.utils
|
||||
|
||||
import org.apache.commons.lang3.builder.StandardToStringStyle
|
||||
import org.apache.commons.lang3.builder.ToStringStyle
|
||||
import java.math.BigInteger
|
||||
import java.util.Random
|
||||
|
||||
class StringUtils {
|
||||
|
||||
companion object {
|
||||
private lateinit var toStringStyle: StandardToStringStyle
|
||||
|
||||
@JvmStatic
|
||||
fun getRandomId(): String {
|
||||
return BigInteger(260, Random()).toString(32).subSequence(0, 32).toString()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun defaultToStringStyle(): ToStringStyle {
|
||||
toStringStyle = StandardToStringStyle()
|
||||
toStringStyle.apply {
|
||||
fieldSeparator = ", "
|
||||
isUseClassName = false
|
||||
isUseIdentityHashCode = false
|
||||
contentStart = "{"
|
||||
contentEnd = "}"
|
||||
fieldNameValueSeparator = ": "
|
||||
arrayStart = "["
|
||||
arrayEnd = "]"
|
||||
}
|
||||
|
||||
return toStringStyle
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun joinLongs(values: LongArray): String {
|
||||
return org.apache.commons.lang3.StringUtils.join(values, ',')
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun splitLongs(str: String): LongArray {
|
||||
val parts: Array<String> = org.apache.commons.lang3.StringUtils.split(str, ',')
|
||||
val numbers = LongArray(parts.size) {
|
||||
i ->
|
||||
parts[i].toLong()
|
||||
}
|
||||
return numbers
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue