AndroidAPS/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java

300 lines
10 KiB
Java
Raw Normal View History

2019-03-22 23:08:13 +01:00
package info.nightscout.androidaps.utils;
2016-06-05 01:40:35 +02:00
2019-05-16 13:57:37 +02:00
import androidx.collection.LongSparseArray;
2017-12-22 02:55:40 +01:00
import org.joda.time.DateTime;
2018-04-01 18:44:58 +02:00
import org.joda.time.format.DateTimeFormat;
2017-12-22 02:55:40 +01:00
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
2017-01-03 19:06:35 +01:00
2016-06-05 01:40:35 +02:00
import java.text.DateFormat;
2019-06-02 16:24:51 +02:00
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
2016-06-05 01:40:35 +02:00
import java.text.SimpleDateFormat;
2016-10-20 23:50:31 +02:00
import java.util.Calendar;
2016-06-05 01:40:35 +02:00
import java.util.Date;
2016-10-20 23:50:31 +02:00
import java.util.GregorianCalendar;
2017-10-02 17:38:45 +02:00
import java.util.Locale;
2016-06-05 01:40:35 +02:00
import java.util.TimeZone;
2016-10-20 23:50:31 +02:00
import java.util.regex.Matcher;
import java.util.regex.Pattern;
2016-06-05 01:40:35 +02:00
2017-01-03 19:06:35 +01:00
import info.nightscout.androidaps.MainApp;
2017-06-26 12:44:03 +02:00
import info.nightscout.androidaps.R;
2017-01-03 19:06:35 +01:00
2016-06-05 01:40:35 +02:00
/**
* The Class DateUtil. A simple wrapper around SimpleDateFormat to ease the handling of iso date string <-> date obj
* with TZ
*/
2016-07-16 22:37:10 +02:00
public class DateUtil {
2016-06-05 01:40:35 +02:00
2016-07-16 22:37:10 +02:00
/**
* The date format in iso.
*/
private static String FORMAT_DATE_ISO_OUT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
2016-06-05 01:40:35 +02:00
/**
* Takes in an ISO date string of the following format:
* yyyy-mm-ddThh:mm:ss.ms+HoMo
*
* @param isoDateString the iso date string
* @return the date
*/
2019-08-05 14:12:39 +02:00
public static Date fromISODateString(String isoDateString) {
2017-12-03 17:34:29 +01:00
2017-12-22 02:55:40 +01:00
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = DateTime.parse(isoDateString, parser);
return dateTime.toDate();
2016-06-05 01:40:35 +02:00
}
/**
* Render date
*
2016-07-16 22:37:10 +02:00
* @param date the date obj
2016-06-05 01:40:35 +02:00
* @param format - if not specified, will use FORMAT_DATE_ISO
2016-07-16 22:37:10 +02:00
* @param tz - tz to set to, if not specified uses local timezone
2016-06-05 01:40:35 +02:00
* @return the iso-formatted date string
*/
2016-07-16 22:37:10 +02:00
public static String toISOString(Date date, String format, TimeZone tz) {
if (format == null) format = FORMAT_DATE_ISO_OUT;
2016-07-16 22:37:10 +02:00
if (tz == null) tz = TimeZone.getDefault();
2017-10-02 17:38:45 +02:00
DateFormat f = new SimpleDateFormat(format, Locale.getDefault());
2016-06-05 01:40:35 +02:00
f.setTimeZone(tz);
return f.format(date);
}
2016-07-16 22:37:10 +02:00
public static String toISOString(Date date) {
return toISOString(date, FORMAT_DATE_ISO_OUT, TimeZone.getTimeZone("UTC"));
2016-07-16 22:37:10 +02:00
}
2017-12-03 17:34:29 +01:00
2016-07-21 00:18:45 +02:00
public static String toISOString(long date) {
return toISOString(new Date(date), FORMAT_DATE_ISO_OUT, TimeZone.getTimeZone("UTC"));
2016-07-21 00:18:45 +02:00
}
2016-10-20 23:50:31 +02:00
2019-06-02 16:24:51 +02:00
public static String toISOAsUTC(final long timestamp) {
final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'0000Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format.format(timestamp);
}
public static String toISONoZone(final long timestamp) {
final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getDefault());
return format.format(timestamp);
}
2016-10-20 23:50:31 +02:00
public static Date toDate(Integer seconds) {
Calendar calendar = new GregorianCalendar();
2018-04-01 18:44:58 +02:00
calendar.set(Calendar.MONTH, 0); // Set january to be sure we miss DST changing
2016-10-20 23:50:31 +02:00
calendar.set(Calendar.HOUR_OF_DAY, seconds / 60 / 60);
calendar.set(Calendar.MINUTE, (seconds / 60) % 60);
calendar.set(Calendar.SECOND, 0);
return calendar.getTime();
}
public static int toSeconds(String hh_colon_mm) {
2019-11-22 10:40:48 +01:00
Pattern p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM| PM|AM|PM|)");
2016-10-20 23:50:31 +02:00
Matcher m = p.matcher(hh_colon_mm);
int retval = 0;
if (m.find()) {
retval = SafeParse.stringToInt(m.group(1)) * 60 * 60 + SafeParse.stringToInt(m.group(2)) * 60;
2019-11-22 10:40:48 +01:00
if ((m.group(3).equals(" a.m.") || m.group(3).equals(" AM") || m.group(3).equals("AM")) && m.group(1).equals("12"))
2017-08-16 19:33:41 +02:00
retval -= 12 * 60 * 60;
2019-11-22 10:40:48 +01:00
if ((m.group(3).equals(" p.m.") || m.group(3).equals(" PM") || m.group(3).equals("PM")) && !(m.group(1).equals("12")))
2017-08-16 19:33:41 +02:00
retval += 12 * 60 * 60;
2016-10-20 23:50:31 +02:00
}
return retval;
}
2017-01-03 19:06:35 +01:00
public static String dateString(Date date) {
2017-01-07 23:26:28 +01:00
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
return df.format(date);
2017-01-03 19:06:35 +01:00
}
public static String dateString(long mills) {
2017-01-07 23:26:28 +01:00
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
return df.format(mills);
2017-01-03 19:06:35 +01:00
}
2019-12-09 19:03:26 +01:00
public static String dateStringShort(long mills) {
String format = "MM/dd";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {
format = "dd/MM";
}
return new DateTime(mills).toString(DateTimeFormat.forPattern(format));
}
2017-01-03 19:06:35 +01:00
public static String timeString(Date date) {
String format = "hh:mma";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {
format = "HH:mm";
}
return new DateTime(date).toString(DateTimeFormat.forPattern(format));
2017-01-03 19:06:35 +01:00
}
public static String timeString(long mills) {
String format = "hh:mma";
if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) {
format = "HH:mm";
}
return new DateTime(mills).toString(DateTimeFormat.forPattern(format));
2017-01-03 19:06:35 +01:00
}
2018-08-17 13:58:06 +02:00
public static String timeFullString(long mills) {
return new DateTime(mills).toString(DateTimeFormat.fullTime());
}
2017-01-03 19:06:35 +01:00
public static String dateAndTimeString(Date date) {
return dateString(date) + " " + timeString(date);
}
2017-12-03 17:34:29 +01:00
2018-04-09 19:52:01 +02:00
public static String dateAndTimeRangeString(long start, long end) {
return dateAndTimeString(start) + " - " + timeString(end);
}
2017-01-03 19:06:35 +01:00
public static String dateAndTimeString(long mills) {
2019-08-05 14:12:39 +02:00
if (mills == 0) return "";
2017-01-03 19:06:35 +01:00
return dateString(mills) + " " + timeString(mills);
}
2017-06-26 12:44:03 +02:00
2018-08-17 13:58:06 +02:00
public static String dateAndTimeFullString(long mills) {
return dateString(mills) + " " + timeFullString(mills);
}
2017-06-26 12:44:03 +02:00
public static String minAgo(long time) {
2018-04-01 18:44:58 +02:00
int mins = (int) ((now() - time) / 1000 / 60);
return MainApp.gs(R.string.minago, mins);
2017-06-26 12:44:03 +02:00
}
2018-06-23 18:24:04 +02:00
public static String minAgoShort(long time) {
Integer mins = (int) ((time - now()) / 1000 / 60);
return (mins > 0 ? "+" : "") + mins.toString();
}
2018-01-29 19:05:39 +01:00
public static String hourAgo(long time) {
2018-04-01 18:44:58 +02:00
double hours = (now() - time) / 1000d / 60 / 60;
return MainApp.gs(R.string.hoursago, hours);
2018-01-29 19:05:39 +01:00
}
2017-10-02 19:57:41 +02:00
private static LongSparseArray<String> timeStrings = new LongSparseArray<>();
public static String timeStringFromSeconds(int seconds) {
String cached = timeStrings.get(seconds);
if (cached != null)
return cached;
2018-04-01 18:44:58 +02:00
String t = timeString(toDate(seconds));
2017-10-02 19:57:41 +02:00
timeStrings.put(seconds, t);
return t;
}
2017-12-03 17:34:29 +01:00
public static String timeFrameString(long timeInMillis) {
long remainingTimeMinutes = timeInMillis / (1000 * 60);
long remainingTimeHours = remainingTimeMinutes / 60;
remainingTimeMinutes = remainingTimeMinutes % 60;
return "(" + ((remainingTimeHours > 0) ? (remainingTimeHours + MainApp.gs(R.string.shorthour) + " ") : "") + remainingTimeMinutes + "')";
2017-10-29 02:06:06 +02:00
}
2017-12-03 17:34:29 +01:00
public static String sinceString(long timestamp) {
return timeFrameString(System.currentTimeMillis() - timestamp);
2017-10-29 02:06:06 +02:00
}
2017-12-03 17:34:29 +01:00
public static String untilString(long timestamp) {
return timeFrameString(timestamp - System.currentTimeMillis());
2017-10-29 02:06:06 +02:00
}
2018-03-26 16:51:25 +02:00
public static long now() {
return System.currentTimeMillis();
}
2017-10-29 02:06:06 +02:00
2018-04-05 09:39:18 +02:00
public static long roundDateToSec(long date) {
return date - date % 1000;
}
2018-09-18 20:17:45 +02:00
2019-03-22 23:08:13 +01:00
public static boolean isCloseToNow(long date) {
long diff = Math.abs(date - now());
return diff < T.mins(2).msecs();
}
2018-09-18 20:17:45 +02:00
public static GregorianCalendar gregorianCalendar() {
return new GregorianCalendar();
}
2019-07-14 20:00:42 +02:00
2019-06-02 16:24:51 +02:00
public static long getTimeZoneOffsetMs() {
return new GregorianCalendar().getTimeZone().getRawOffset();
}
public static int getTimeZoneOffsetMinutes(final long timestamp) {
return TimeZone.getDefault().getOffset(timestamp) / 60000;
}
public static String niceTimeScalar(long t) {
String unit = MainApp.gs(R.string.unit_second);
t = t / 1000;
if (t != 1) unit = MainApp.gs(R.string.unit_seconds);
if (t > 59) {
unit = MainApp.gs(R.string.unit_minute);
t = t / 60;
if (t != 1) unit = MainApp.gs(R.string.unit_minutes);
if (t > 59) {
unit = MainApp.gs(R.string.unit_hour);
t = t / 60;
if (t != 1) unit = MainApp.gs(R.string.unit_hours);
if (t > 24) {
2019-07-15 12:33:03 +02:00
unit = MainApp.gs(R.string.unit_day) + "\"";
2019-06-02 16:24:51 +02:00
t = t / 24;
2019-07-15 12:33:03 +02:00
if (t != 1) unit = MainApp.gs(R.string.unit_days) + "\"";
2019-06-02 16:24:51 +02:00
if (t > 28) {
2019-07-15 12:33:03 +02:00
unit = MainApp.gs(R.string.unit_week) + "\"";
2019-06-02 16:24:51 +02:00
t = t / 7;
2019-07-15 12:33:03 +02:00
if (t != 1) unit = MainApp.gs(R.string.unit_weeks) + "\"";
2019-06-02 16:24:51 +02:00
}
}
}
}
//if (t != 1) unit = unit + "s"; //implemented plurality in every step, because in other languages plurality of time is not every time adding the same character
return qs((double) t, 0) + " " + unit;
}
// singletons to avoid repeated allocation
private static DecimalFormatSymbols dfs;
private static DecimalFormat df;
public static String qs(double x, int digits) {
if (digits == -1) {
digits = 0;
if (((int) x != x)) {
digits++;
if ((((int) x * 10) / 10 != x)) {
digits++;
if ((((int) x * 100) / 100 != x)) digits++;
}
}
}
if (dfs == null) {
final DecimalFormatSymbols local_dfs = new DecimalFormatSymbols();
local_dfs.setDecimalSeparator('.');
dfs = local_dfs; // avoid race condition
}
final DecimalFormat this_df;
// use singleton if on ui thread otherwise allocate new as DecimalFormat is not thread safe
if (Thread.currentThread().getId() == 1) {
if (df == null) {
final DecimalFormat local_df = new DecimalFormat("#", dfs);
local_df.setMinimumIntegerDigits(1);
df = local_df; // avoid race condition
}
this_df = df;
} else {
this_df = new DecimalFormat("#", dfs);
}
this_df.setMaximumFractionDigits(digits);
return this_df.format(x);
}
2017-10-29 02:06:06 +02:00
}