|
|
/*
|
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
|
*
|
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
|
*/
|
|
|
|
|
|
package com.todoroo.andlib.utility;
|
|
|
|
|
|
import static org.tasks.date.DateTimeUtils.newDateTime;
|
|
|
|
|
|
import android.content.Context;
|
|
|
import android.text.format.DateFormat;
|
|
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
|
|
import org.tasks.data.entity.Task;
|
|
|
|
|
|
import org.tasks.BuildConfig;
|
|
|
import org.tasks.R;
|
|
|
import org.tasks.time.DateTime;
|
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.time.format.FormatStyle;
|
|
|
import java.time.format.TextStyle;
|
|
|
import java.util.Locale;
|
|
|
|
|
|
public class DateUtilities {
|
|
|
|
|
|
/** Represents a single hour */
|
|
|
public static final long ONE_HOUR = 3600000L;
|
|
|
/** Represents a single day */
|
|
|
public static final long ONE_DAY = 24 * ONE_HOUR;
|
|
|
/** Represents a single week */
|
|
|
public static final long ONE_WEEK = 7 * ONE_DAY;
|
|
|
/** Represents a single minute */
|
|
|
public static final long ONE_MINUTE = 60000L;
|
|
|
|
|
|
static Boolean is24HourOverride = null;
|
|
|
|
|
|
/* ======================================================================
|
|
|
* =========================================================== formatters
|
|
|
* ====================================================================== */
|
|
|
|
|
|
private static boolean is24HourFormat(Context context) {
|
|
|
return BuildConfig.DEBUG && is24HourOverride != null
|
|
|
? is24HourOverride
|
|
|
: DateFormat.is24HourFormat(context);
|
|
|
}
|
|
|
|
|
|
public static String getTimeString(Context context, DateTime date) {
|
|
|
String value;
|
|
|
if (is24HourFormat(context)) {
|
|
|
value = "HH:mm";
|
|
|
} else if (date.getMinuteOfHour() == 0) {
|
|
|
value = "h a";
|
|
|
} else {
|
|
|
value = "h:mm a";
|
|
|
}
|
|
|
return date.toString(value);
|
|
|
}
|
|
|
|
|
|
public static String getLongDateString(DateTime date, java.util.Locale locale) {
|
|
|
return getFullDate(date, locale, FormatStyle.LONG);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @param date date to format
|
|
|
* @return date, with month, day, and year
|
|
|
*/
|
|
|
public static String getDateString(Context context, DateTime date) {
|
|
|
return getRelativeDay(
|
|
|
context, date.getMillis(), Locale.getDefault(), FormatStyle.MEDIUM);
|
|
|
}
|
|
|
|
|
|
static String getWeekday(DateTime date, java.util.Locale locale) {
|
|
|
return date.toLocalDate().getDayOfWeek().getDisplayName(TextStyle.FULL, locale);
|
|
|
}
|
|
|
|
|
|
/** @return weekday */
|
|
|
public static String getWeekdayShort(DateTime date, java.util.Locale locale) {
|
|
|
return date.toLocalDate().getDayOfWeek().getDisplayName(TextStyle.SHORT, locale);
|
|
|
}
|
|
|
|
|
|
public static String getLongDateStringWithTime(long timestamp, java.util.Locale locale) {
|
|
|
return getFullDateTime(newDateTime(timestamp), locale, FormatStyle.LONG);
|
|
|
}
|
|
|
|
|
|
public static String getRelativeDateTime(
|
|
|
Context context, long date, java.util.Locale locale, FormatStyle style) {
|
|
|
return getRelativeDateTime(context, date, locale, style, false, false);
|
|
|
}
|
|
|
|
|
|
public static String getRelativeDateTime(
|
|
|
Context context, long date, java.util.Locale locale, FormatStyle style, boolean lowercase) {
|
|
|
return getRelativeDateTime(context, date, locale, style, false, lowercase);
|
|
|
}
|
|
|
|
|
|
public static String getRelativeDateTime(
|
|
|
Context context, long date, java.util.Locale locale, FormatStyle style, boolean alwaysDisplayFullDate, boolean lowercase) {
|
|
|
|
|
|
if(alwaysDisplayFullDate || !isWithinSixDays(date)) {
|
|
|
return Task.hasDueTime(date)
|
|
|
? getFullDateTime(newDateTime(date), locale, style)
|
|
|
: getFullDate(newDateTime(date), locale, style);
|
|
|
}
|
|
|
|
|
|
String day = getRelativeDay(context, date, locale, isAbbreviated(style), lowercase);
|
|
|
if (Task.hasDueTime(date)) {
|
|
|
String time = getTimeString(context, newDateTime(date));
|
|
|
return newDateTime().startOfDay().equals(newDateTime(date).startOfDay()) ? time : String.format("%s %s", day, time);
|
|
|
} else {
|
|
|
return day;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static boolean isAbbreviated(FormatStyle style) {
|
|
|
return style == FormatStyle.SHORT || style == FormatStyle.MEDIUM;
|
|
|
}
|
|
|
|
|
|
public static String getRelativeDay(
|
|
|
Context context,
|
|
|
long date,
|
|
|
java.util.Locale locale,
|
|
|
FormatStyle style) {
|
|
|
return getRelativeDay(context, date, locale, style, false,false);
|
|
|
}
|
|
|
|
|
|
public static String getRelativeDay(
|
|
|
Context context,
|
|
|
long date,
|
|
|
java.util.Locale locale,
|
|
|
FormatStyle style,
|
|
|
boolean alwaysDisplayFullDate,
|
|
|
boolean lowercase) {
|
|
|
if(alwaysDisplayFullDate) {
|
|
|
return getFullDate(newDateTime(date), locale, style);
|
|
|
}
|
|
|
return isWithinSixDays(date)
|
|
|
? getRelativeDay(context, date, locale, isAbbreviated(style), lowercase)
|
|
|
: getFullDate(newDateTime(date), locale, style);
|
|
|
}
|
|
|
|
|
|
private static String getFullDate(DateTime date, java.util.Locale locale, FormatStyle style) {
|
|
|
return stripYear(
|
|
|
DateTimeFormatter.ofLocalizedDate(style)
|
|
|
.withLocale(locale)
|
|
|
.format(date.toLocalDate()),
|
|
|
newDateTime().getYear());
|
|
|
}
|
|
|
|
|
|
private static String getFullDateTime(DateTime date, java.util.Locale locale, FormatStyle style) {
|
|
|
return stripYear(
|
|
|
DateTimeFormatter.ofLocalizedDateTime(style, FormatStyle.SHORT)
|
|
|
.withLocale(locale)
|
|
|
.format(date.toLocalDateTime()),
|
|
|
newDateTime().getYear());
|
|
|
}
|
|
|
|
|
|
private static String stripYear(String date, int year) {
|
|
|
return date.replaceAll("(?: de |, |/| )?" + year + "(?:年|년 | г\\.)?", "");
|
|
|
}
|
|
|
|
|
|
private static @Nullable String getRelativeDay(Context context, long date, java.util.Locale locale, boolean abbreviated, boolean lowercase) {
|
|
|
DateTime startOfToday = newDateTime().startOfDay();
|
|
|
DateTime startOfDate = newDateTime(date).startOfDay();
|
|
|
|
|
|
if (startOfToday.equals(startOfDate)) {
|
|
|
return context.getString(lowercase ? R.string.today_lowercase : R.string.today);
|
|
|
}
|
|
|
|
|
|
if (startOfToday.plusDays(1).equals(startOfDate)) {
|
|
|
return context.getString(
|
|
|
abbreviated
|
|
|
? lowercase ? R.string.tomorrow_abbrev_lowercase : R.string.tmrw
|
|
|
: lowercase ? R.string.tomorrow_lowercase : R.string.tomorrow);
|
|
|
}
|
|
|
|
|
|
if (startOfDate.plusDays(1).equals(startOfToday)) {
|
|
|
return context.getString(
|
|
|
abbreviated
|
|
|
? lowercase ? R.string.yesterday_abbrev_lowercase : R.string.yest
|
|
|
: lowercase ? R.string.yesterday_lowercase : R.string.yesterday);
|
|
|
}
|
|
|
|
|
|
DateTime dateTime = newDateTime(date);
|
|
|
return abbreviated
|
|
|
? DateUtilities.getWeekdayShort(dateTime, locale)
|
|
|
: DateUtilities.getWeekday(dateTime, locale);
|
|
|
}
|
|
|
|
|
|
private static boolean isWithinSixDays(long date){
|
|
|
DateTime startOfToday = newDateTime().startOfDay();
|
|
|
DateTime startOfDate = newDateTime(date).startOfDay();
|
|
|
return Math.abs(startOfToday.getMillis() - startOfDate.getMillis()) <= DateUtilities.ONE_DAY * 6;
|
|
|
}
|
|
|
|
|
|
}
|