package org.wordpress.android.util;
import android.content.Context;
import android.text.TextUtils;
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);
}
};
public static String javaDateToTimeSpan(final Date date, Context context, long currentTime) {
if (date == null) {
return "";
}
long passedTime = date.getTime();
// return "now" if less than a minute has elapsed
long secondsSince = (currentTime - passedTime) / 1000;
if (secondsSince < 60) {
return context.getString(R.string.timespan_now);
}
long daysSince = secondsSince / (60 * 60 * 24);
// less than a year old, let `DateUtils.getRelativeTimeSpanString` do the job
if (daysSince < 365) {
return DateUtils.getRelativeTimeSpanString(passedTime, currentTime,
DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_ALL).toString();
}
// date is older, so include year (ex: Jan 30, 2013)
return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_ABBREV_ALL);
}
/**
* Converts a date to a localized relative time span ("Now", "8 hr. ago", "Yesterday", "3 days ago", "Jul 10, 1940")
* We're using a call to `DateUtils.getRelativeTimeSpanString` in most cases.
*/
public static String javaDateToTimeSpan(final Date date, Context context) {
return javaDateToTimeSpan(date, context, System.currentTimeMillis());
}
/**
* 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.
*
* @return 0 if the parameter is null, empty or not a date.
*/
public static long timestampFromIso8601Millis(final String strDate) {
if (TextUtils.isEmpty(strDate)) {
return 0;
}
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);
}
}