| package org.wordpress.android.util; |
| |
| import android.content.Context; |
| import android.text.format.DateUtils; |
| |
| import java.text.DateFormat; |
| import java.text.ParseException; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.Locale; |
| import java.util.TimeZone; |
| |
| public class DateTimeUtils { |
| private DateTimeUtils() { |
| throw new AssertionError(); |
| } |
| |
| // See http://drdobbs.com/java/184405382 |
| private static final ThreadLocal<DateFormat> ISO8601_FORMAT = new ThreadLocal<DateFormat>() { |
| @Override |
| protected DateFormat initialValue() { |
| return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); |
| } |
| }; |
| |
| /** |
| * Converts a date to a relative time span ("8h", "3d", etc.) - similar to |
| * DateUtils.getRelativeTimeSpanString but returns shorter result |
| */ |
| public static String javaDateToTimeSpan(final Date date, Context context) { |
| if (date == null) { |
| return ""; |
| } |
| |
| long passedTime = date.getTime(); |
| long currentTime = System.currentTimeMillis(); |
| |
| // return "now" if less than a minute has elapsed |
| long secondsSince = (currentTime - passedTime) / 1000; |
| if (secondsSince < 60) { |
| return context.getString(R.string.timespan_now); |
| } |
| |
| // less than an hour (ex: 12m) |
| long minutesSince = secondsSince / 60; |
| if (minutesSince < 60) { |
| return Long.toString(minutesSince) + "m"; |
| } |
| |
| // less than a day (ex: 17h) |
| long hoursSince = minutesSince / 60; |
| if (hoursSince < 24) { |
| return Long.toString(hoursSince) + "h"; |
| } |
| |
| // less than a week (ex: 5d) |
| long daysSince = hoursSince / 24; |
| if (daysSince < 7) { |
| return Long.toString(daysSince) + "d"; |
| } |
| |
| // less than a year old, so return day/month without year (ex: Jan 30) |
| if (daysSince < 365) { |
| return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_NO_YEAR | |
| DateUtils.FORMAT_ABBREV_ALL); |
| } |
| |
| // date is older, so include year (ex: Jan 30, 2013) |
| return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_ABBREV_ALL); |
| } |
| |
| /** |
| * Given an ISO 8601-formatted date as a String, returns a {@link Date}. |
| */ |
| public static Date dateFromIso8601(final String strDate) { |
| try { |
| DateFormat formatter = ISO8601_FORMAT.get(); |
| return formatter.parse(strDate); |
| } catch (ParseException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Given an ISO 8601-formatted date as a String, returns a {@link Date} in UTC. |
| */ |
| public static Date dateUTCFromIso8601(String iso8601date) { |
| try { |
| iso8601date = iso8601date.replace("Z", "+0000").replace("+00:00", "+0000"); |
| DateFormat formatter = ISO8601_FORMAT.get(); |
| formatter.setTimeZone(TimeZone.getTimeZone("UTC")); |
| return formatter.parse(iso8601date); |
| } catch (ParseException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Given a {@link Date}, returns an ISO 8601-formatted String. |
| */ |
| public static String iso8601FromDate(Date date) { |
| if (date == null) { |
| return ""; |
| } |
| DateFormat formatter = ISO8601_FORMAT.get(); |
| return formatter.format(date); |
| } |
| |
| /** |
| * Given a {@link Date}, returns an ISO 8601-formatted String in UTC. |
| */ |
| public static String iso8601UTCFromDate(Date date) { |
| if (date == null) { |
| return ""; |
| } |
| TimeZone tz = TimeZone.getTimeZone("UTC"); |
| DateFormat formatter = ISO8601_FORMAT.get(); |
| formatter.setTimeZone(tz); |
| |
| String iso8601date = formatter.format(date); |
| |
| // Use "+00:00" notation rather than "+0000" to be consistent with the WP.COM API |
| return iso8601date.replace("+0000", "+00:00"); |
| } |
| |
| /** |
| * Returns the current UTC date |
| */ |
| public static Date nowUTC() { |
| Date dateTimeNow = new Date(); |
| return localDateToUTC(dateTimeNow); |
| } |
| |
| public static Date localDateToUTC(Date dtLocal) { |
| if (dtLocal == null) { |
| return null; |
| } |
| TimeZone tz = TimeZone.getDefault(); |
| int currentOffsetFromUTC = tz.getRawOffset() + (tz.inDaylightTime(dtLocal) ? tz.getDSTSavings() : 0); |
| return new Date(dtLocal.getTime() - currentOffsetFromUTC); |
| } |
| |
| // Routines to return a diff between two dates - always return a positive number |
| |
| public static int daysBetween(Date dt1, Date dt2) { |
| long hrDiff = hoursBetween(dt1, dt2); |
| if (hrDiff == 0) { |
| return 0; |
| } |
| return (int) (hrDiff / 24); |
| } |
| |
| public static int hoursBetween(Date dt1, Date dt2) { |
| long minDiff = minutesBetween(dt1, dt2); |
| if (minDiff == 0) { |
| return 0; |
| } |
| return (int) (minDiff / 60); |
| } |
| |
| public static int minutesBetween(Date dt1, Date dt2) { |
| long msDiff = millisecondsBetween(dt1, dt2); |
| if (msDiff == 0) { |
| return 0; |
| } |
| return (int) (msDiff / 60000); |
| } |
| |
| public static int secondsBetween(Date dt1, Date dt2) { |
| long msDiff = millisecondsBetween(dt1, dt2); |
| if (msDiff == 0) { |
| return 0; |
| } |
| return (int) (msDiff / 1000); |
| } |
| |
| public static long millisecondsBetween(Date dt1, Date dt2) { |
| if (dt1 == null || dt2 == null) { |
| return 0; |
| } |
| return Math.abs(dt1.getTime() - dt2.getTime()); |
| } |
| |
| public static boolean isSameYear(Date dt1, Date dt2) { |
| if (dt1 == null || dt2 == null) { |
| return false; |
| } |
| return dt1.getYear() == dt2.getYear(); |
| } |
| |
| public static boolean isSameMonthAndYear(Date dt1, Date dt2) { |
| if (dt1 == null || dt2 == null) { |
| return false; |
| } |
| return dt1.getYear() == dt2.getYear() && dt1.getMonth() == dt2.getMonth(); |
| } |
| |
| // Routines involving Unix timestamps (GMT assumed) |
| |
| /** |
| * Given an ISO 8601-formatted date as a String, returns the corresponding UNIX timestamp. |
| */ |
| public static long timestampFromIso8601(final String strDate) { |
| return (timestampFromIso8601Millis(strDate) / 1000); |
| } |
| |
| /** |
| * Given an ISO 8601-formatted date as a String, returns the corresponding timestamp in milliseconds. |
| */ |
| public static long timestampFromIso8601Millis(final String strDate) { |
| Date date = dateFromIso8601(strDate); |
| if (date == null) { |
| return 0; |
| } |
| return (date.getTime()); |
| } |
| |
| /** |
| * Given a UNIX timestamp, returns the corresponding {@link Date}. |
| */ |
| public static Date dateFromTimestamp(long timestamp) { |
| return new java.util.Date(timestamp * 1000); |
| } |
| |
| /** |
| * Given a UNIX timestamp, returns an ISO 8601-formatted date as a String. |
| */ |
| public static String iso8601FromTimestamp(long timestamp) { |
| return iso8601FromDate(dateFromTimestamp(timestamp)); |
| } |
| |
| /** |
| * Given a UNIX timestamp, returns an ISO 8601-formatted date in UTC as a String. |
| */ |
| public static String iso8601UTCFromTimestamp(long timestamp) { |
| return iso8601UTCFromDate(dateFromTimestamp(timestamp)); |
| } |
| |
| /** |
| * Given a UNIX timestamp, returns a relative time span ("8h", "3d", etc.). |
| */ |
| public static String timeSpanFromTimestamp(long timestamp, Context context) { |
| Date dateGMT = dateFromTimestamp(timestamp); |
| return javaDateToTimeSpan(dateGMT, context); |
| } |
| } |