2018-02-26 17:58:18 +00:00
|
|
|
/*
|
2014-04-12 23:53:05 +00:00
|
|
|
* Copyright (C) 2014 Open Whisper Systems
|
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
* This program 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/>.
|
|
|
|
*/
|
2014-01-08 22:29:05 +00:00
|
|
|
package org.thoughtcrime.securesms.util;
|
|
|
|
|
|
|
|
import android.content.Context;
|
2015-11-19 06:32:33 +00:00
|
|
|
import android.os.Build;
|
2017-01-24 00:44:38 +00:00
|
|
|
import android.support.annotation.NonNull;
|
2015-01-15 21:35:35 +00:00
|
|
|
import android.text.format.DateFormat;
|
|
|
|
|
2015-02-05 23:16:57 +00:00
|
|
|
import org.thoughtcrime.securesms.R;
|
|
|
|
|
2018-02-26 17:58:18 +00:00
|
|
|
import java.text.SimpleDateFormat;
|
2015-03-19 20:08:48 +00:00
|
|
|
import java.util.Date;
|
2018-02-26 17:58:18 +00:00
|
|
|
import java.util.Locale;
|
2015-02-05 23:16:57 +00:00
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
2014-01-08 22:29:05 +00:00
|
|
|
/**
|
2014-04-12 23:53:05 +00:00
|
|
|
* Utility methods to help display dates in a nice, easily readable way.
|
2014-01-08 22:29:05 +00:00
|
|
|
*/
|
|
|
|
public class DateUtils extends android.text.format.DateUtils {
|
|
|
|
|
2018-02-26 17:58:18 +00:00
|
|
|
@SuppressWarnings("unused")
|
2018-07-12 23:03:32 +00:00
|
|
|
private static final String TAG = DateUtils.class.getSimpleName();
|
2018-06-26 17:27:44 +00:00
|
|
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
|
2018-02-26 17:58:18 +00:00
|
|
|
|
2015-02-05 23:16:57 +00:00
|
|
|
private static boolean isWithin(final long millis, final long span, final TimeUnit unit) {
|
|
|
|
return System.currentTimeMillis() - millis <= unit.toMillis(span);
|
|
|
|
}
|
2014-01-08 22:29:05 +00:00
|
|
|
|
2017-01-24 00:44:38 +00:00
|
|
|
private static boolean isYesterday(final long when) {
|
|
|
|
return DateUtils.isToday(when + TimeUnit.DAYS.toMillis(1));
|
|
|
|
}
|
|
|
|
|
2015-02-05 23:16:57 +00:00
|
|
|
private static int convertDelta(final long millis, TimeUnit to) {
|
|
|
|
return (int) to.convert(System.currentTimeMillis() - millis, TimeUnit.MILLISECONDS);
|
2014-01-08 22:29:05 +00:00
|
|
|
}
|
|
|
|
|
2015-03-19 20:08:48 +00:00
|
|
|
private static String getFormattedDateTime(long time, String template, Locale locale) {
|
2015-11-19 06:32:33 +00:00
|
|
|
final String localizedPattern = getLocalizedPattern(template, locale);
|
2015-03-19 20:08:48 +00:00
|
|
|
return new SimpleDateFormat(localizedPattern, locale).format(new Date(time));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getBriefRelativeTimeSpanString(final Context c, final Locale locale, final long timestamp) {
|
2015-02-05 23:16:57 +00:00
|
|
|
if (isWithin(timestamp, 1, TimeUnit.MINUTES)) {
|
2016-10-08 17:57:49 +00:00
|
|
|
return c.getString(R.string.DateUtils_just_now);
|
2015-02-05 23:16:57 +00:00
|
|
|
} else if (isWithin(timestamp, 1, TimeUnit.HOURS)) {
|
|
|
|
int mins = convertDelta(timestamp, TimeUnit.MINUTES);
|
2015-06-03 18:37:13 +00:00
|
|
|
return c.getResources().getString(R.string.DateUtils_minutes_ago, mins);
|
2015-02-05 23:16:57 +00:00
|
|
|
} else if (isWithin(timestamp, 1, TimeUnit.DAYS)) {
|
|
|
|
int hours = convertDelta(timestamp, TimeUnit.HOURS);
|
|
|
|
return c.getResources().getQuantityString(R.plurals.hours_ago, hours, hours);
|
|
|
|
} else if (isWithin(timestamp, 6, TimeUnit.DAYS)) {
|
2015-03-19 20:08:48 +00:00
|
|
|
return getFormattedDateTime(timestamp, "EEE", locale);
|
2015-02-05 23:16:57 +00:00
|
|
|
} else if (isWithin(timestamp, 365, TimeUnit.DAYS)) {
|
2015-03-19 20:08:48 +00:00
|
|
|
return getFormattedDateTime(timestamp, "MMM d", locale);
|
2015-02-05 23:16:57 +00:00
|
|
|
} else {
|
2015-03-19 20:08:48 +00:00
|
|
|
return getFormattedDateTime(timestamp, "MMM d, yyyy", locale);
|
2015-02-05 23:16:57 +00:00
|
|
|
}
|
2014-01-08 22:29:05 +00:00
|
|
|
}
|
|
|
|
|
2015-03-19 20:08:48 +00:00
|
|
|
public static String getExtendedRelativeTimeSpanString(final Context c, final Locale locale, final long timestamp) {
|
2015-02-05 23:16:57 +00:00
|
|
|
if (isWithin(timestamp, 1, TimeUnit.MINUTES)) {
|
2016-10-08 17:57:49 +00:00
|
|
|
return c.getString(R.string.DateUtils_just_now);
|
2015-02-05 23:16:57 +00:00
|
|
|
} else if (isWithin(timestamp, 1, TimeUnit.HOURS)) {
|
|
|
|
int mins = (int)TimeUnit.MINUTES.convert(System.currentTimeMillis() - timestamp, TimeUnit.MILLISECONDS);
|
2015-06-03 18:37:13 +00:00
|
|
|
return c.getResources().getString(R.string.DateUtils_minutes_ago, mins);
|
2015-02-05 23:16:57 +00:00
|
|
|
} else {
|
2015-03-19 20:08:48 +00:00
|
|
|
StringBuilder format = new StringBuilder();
|
|
|
|
if (isWithin(timestamp, 6, TimeUnit.DAYS)) format.append("EEE ");
|
|
|
|
else if (isWithin(timestamp, 365, TimeUnit.DAYS)) format.append("MMM d, ");
|
|
|
|
else format.append("MMM d, yyyy, ");
|
|
|
|
|
|
|
|
if (DateFormat.is24HourFormat(c)) format.append("HH:mm");
|
|
|
|
else format.append("hh:mm a");
|
|
|
|
|
|
|
|
return getFormattedDateTime(timestamp, format.toString(), locale);
|
2014-01-08 22:29:05 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-15 21:35:35 +00:00
|
|
|
|
2015-11-24 00:25:04 +00:00
|
|
|
public static String getDayPrecisionTimeSpanString(Context context, Locale locale, long timestamp) {
|
|
|
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
|
|
|
|
|
|
|
|
if (simpleDateFormat.format(System.currentTimeMillis()).equals(simpleDateFormat.format(timestamp))) {
|
2015-12-02 07:35:07 +00:00
|
|
|
return context.getString(R.string.DeviceListItem_today);
|
2015-11-24 00:25:04 +00:00
|
|
|
} else {
|
|
|
|
String format;
|
|
|
|
|
|
|
|
if (isWithin(timestamp, 6, TimeUnit.DAYS)) format = "EEE ";
|
|
|
|
else if (isWithin(timestamp, 365, TimeUnit.DAYS)) format = "MMM d";
|
|
|
|
else format = "MMM d, yyy";
|
|
|
|
|
|
|
|
return getFormattedDateTime(timestamp, format, locale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-19 20:08:48 +00:00
|
|
|
public static SimpleDateFormat getDetailedDateFormatter(Context context, Locale locale) {
|
2015-01-15 21:35:35 +00:00
|
|
|
String dateFormatPattern;
|
|
|
|
|
|
|
|
if (DateFormat.is24HourFormat(context)) {
|
2015-11-19 06:32:33 +00:00
|
|
|
dateFormatPattern = getLocalizedPattern("MMM d, yyyy HH:mm:ss zzz", locale);
|
2015-01-15 21:35:35 +00:00
|
|
|
} else {
|
2015-11-19 06:32:33 +00:00
|
|
|
dateFormatPattern = getLocalizedPattern("MMM d, yyyy hh:mm:ss a zzz", locale);
|
2015-01-15 21:35:35 +00:00
|
|
|
}
|
|
|
|
|
2015-03-19 20:08:48 +00:00
|
|
|
return new SimpleDateFormat(dateFormatPattern, locale);
|
2015-01-15 21:35:35 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 00:44:38 +00:00
|
|
|
public static String getRelativeDate(@NonNull Context context,
|
|
|
|
@NonNull Locale locale,
|
|
|
|
long timestamp)
|
|
|
|
{
|
|
|
|
if (isToday(timestamp)) {
|
|
|
|
return context.getString(R.string.DateUtils_today);
|
|
|
|
} else if (isYesterday(timestamp)) {
|
|
|
|
return context.getString(R.string.DateUtils_yesterday);
|
|
|
|
} else {
|
|
|
|
return getFormattedDateTime(timestamp, "EEE, MMM d, yyyy", locale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-26 17:27:44 +00:00
|
|
|
public static boolean isSameDay(long t1, long t2) {
|
|
|
|
return DATE_FORMAT.format(new Date(t1)).equals(DATE_FORMAT.format(new Date(t2)));
|
|
|
|
}
|
|
|
|
|
2018-08-06 14:34:02 +00:00
|
|
|
public static boolean isSameExtendedRelativeTimestamp(@NonNull Context context, @NonNull Locale locale, long t1, long t2) {
|
|
|
|
return getExtendedRelativeTimeSpanString(context, locale, t1).equals(getExtendedRelativeTimeSpanString(context, locale, t2));
|
2018-06-26 17:27:44 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 06:32:33 +00:00
|
|
|
private static String getLocalizedPattern(String template, Locale locale) {
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
|
|
return DateFormat.getBestDateTimePattern(locale, template);
|
|
|
|
} else {
|
|
|
|
return new SimpleDateFormat(template, locale).toLocalizedPattern();
|
|
|
|
}
|
|
|
|
}
|
2014-01-08 22:29:05 +00:00
|
|
|
}
|