/* * This file is part of VIUtils. * * Copyright © 2012-2015 Visual Illusions Entertainment * * VIUtils is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License along with this library. * If not, see http://www.gnu.org/licenses/lgpl.html. */ package net.visualillusionsent.utils; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import java.util.concurrent.TimeUnit; import static net.visualillusionsent.utils.Verify.notEmpty; import static net.visualillusionsent.utils.Verify.notNegative; import static net.visualillusionsent.utils.Verify.notNull; /** * Provides static methods to help with {@link Date} manipulations * * @author Jason (darkdiplomat) * @version 1.1 * @since 1.0.0 */ public final class DateUtils { /* 1.1 @ VIUtils 1.4.0 */ private static final float classVersion = 1.1F; /** Date Format as dd-MMM-yyyy */ private static final DateFormat date_form = new SimpleDateFormat("dd-MMM-yyyy"); /** Date Format as HH:mm:ss */ private static final DateFormat time_form = new SimpleDateFormat("HH:mm:ss"); /** Date Format as dd-MMM-yyyy HH:mm:ss */ private static final DateFormat datetime_form = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); /** Date Format as HH:mm:ss dd-MMM-yyyy */ private static final DateFormat timedate_form = new SimpleDateFormat("HH:mm:ss dd-MMM-yyyy"); /** This class should never be externally constructed */ private DateUtils() { } /** * Returns the Date as a {@link String} formatted as dd-MMM-yyyy * * @param time * the time in milliseconds * * @return date as a string formatted as dd-MMM-yyyy * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToDate(long time) { return longToDate(time, TimeZone.getDefault()); } /** * Returns the Date as a {@link String} formatted as dd-MMM-yyyy for the given TimeZone * * @param time * the time in milliseconds * @param zone * the TimeZone to use * * @return date as a string formatted as dd-MMM-yyyy * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToDate(long time, TimeZone zone) { notNegative(time, "Time"); if (zone != null && zone != TimeZone.getDefault()) { date_form.setTimeZone(zone); } return date_form.format(parseCal(time, zone).getTime()); } /** * Returns the Time as a {@link String} formatted as HH:mm:ss * * @param time * the time in milliseconds * * @return time as a string formatted as HH:mm:ss * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToTime(long time) { return longToTime(time, TimeZone.getDefault()); } /** * Returns the Time as a {@link String} formatted as HH:mm:ss in given TimeZone * * @param time * the time in milliseconds * * @return time as a string formatted as HH:mm:ss * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToTime(long time, TimeZone zone) { notNegative(time, "Time"); if (zone != null && zone != TimeZone.getDefault()) { time_form.setTimeZone(zone); } return time_form.format(parseCal(time, zone).getTime()); } /** * Returns the Date and Time as a {@link String} formatted as dd-MMM-yyyy HH:mm:ss * * @param time * the time in milliseconds * * @return date and time as a string formatted as dd-MMM-yyyy HH:mm:ss * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToDateTime(long time) { return longToDateTime(time, TimeZone.getDefault()); } /** * Returns the Date and Time as a {@link String} formatted as dd-MMM-yyyy HH:mm:ss in given TimeZone * * @param time * the time in milliseconds * @param zone * the TimeZone to use * * @return date and time as a string formatted as dd-MMM-yyyy HH:mm:ss * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToDateTime(long time, TimeZone zone) { notNegative(time, "Time"); if (zone != null && zone != TimeZone.getDefault()) { datetime_form.setTimeZone(zone); } return datetime_form.format(parseCal(time, zone).getTime()); } /** * Returns the Time and Date as a {@link String} formatted as HH:mm:ss dd-MMM-yyyy * * @param time * the time in milliseconds * * @return date and time as a string formatted as HH:mm:ss dd-MMM-yyyy */ public static String longToTimeDate(long time) { return longToTimeDate(time, TimeZone.getDefault()); } /** * Returns the Time and Date as a {@link String} formatted as HH:mm:ss dd-MMM-yyyy in given TimeZone * * @param time * the time in milliseconds * @param zone * the TimeZone to use * * @return date and time as a string formatted as HH:mm:ss dd-MMM-yyyy * * @throws java.lang.IllegalArgumentException * if time is negative */ public static String longToTimeDate(long time, TimeZone zone) { notNegative(time, "Time"); if (zone != null && zone != TimeZone.getDefault()) { timedate_form.setTimeZone(zone); } return timedate_form.format(parseCal(time, zone).getTime()); } /** * Returns the Date and/or Time as a {@link String} formatted as specified * * @param time * the time in milliseconds as per: the difference between the current time and 00:00:00 January 1, 1970 UTC. * @param format * the format to use * * @return date and time as a string formatted as specified * * @throws java.lang.IllegalArgumentException * if time is negative or if format is empty * @throws java.lang.NullPointerException * if format is null */ public static String longToFormatedDateTime(long time, String format) { notNegative(time, "Time"); notNull(format, "String format"); notEmpty(format, "String format"); //Create a Date object from the time given Date date = new Date(time); //Create DateFormat object and verify the format is valid DateFormat form = new SimpleDateFormat(format); //Format it and return return form.format(date); } /** * Parses a {@link String} date into a {@link Date} object * * @param date * the {@link String} representation of the Date * * @return {@link Date} parsed from the date parameter * * @throws java.lang.IllegalArgumentException * if date is empty or date is unable to be parsed * @throws java.lang.NullPointerException * if date is null */ public static Date getDateFromString(String date) { notNull(date, "String date"); notEmpty(date, "String date"); Date theDate; try { theDate = datetime_form.parse(date); } catch (ParseException pe) { throw new IllegalArgumentException(pe.getMessage()); } return theDate; } /** * Parses a {@link Date} object into a {@link String} date. * This is a String that can later be passed to {@link DateUtils#getDateFromString(java.lang.String)}. * * The format here is: "dd-MMM-yyyy HH:mm:ss" * * @param date * the {@link Date} to parse into a {@link String}. * * @return {@link String} formatted from the date parameter */ public static String getStringFromDate(Date date) { notNull(date, "String date"); return datetime_form.format(date); } private static Calendar parseCal(long time, TimeZone to) { Calendar calendar = Calendar.getInstance(); TimeZone fromTimeZone = calendar.getTimeZone(); TimeZone toTimeZone = to != null ? to : TimeZone.getTimeZone("GMT"); calendar.setTimeZone(fromTimeZone); calendar.add(Calendar.MILLISECOND, fromTimeZone.getRawOffset() * -1); if (fromTimeZone.inDaylightTime(calendar.getTime())) { calendar.add(Calendar.MILLISECOND, calendar.getTimeZone().getDSTSavings() * -1); } calendar.add(Calendar.MILLISECOND, toTimeZone.getRawOffset()); if (toTimeZone.inDaylightTime(calendar.getTime())) { calendar.add(Calendar.MILLISECOND, toTimeZone.getDSTSavings()); } calendar.setTimeInMillis(time); return calendar; } /** * Get the Unix timestamp for the current time.<br> * The time in seconds since January 01 1970 * * @return {@code long} timestamp */ public static long getUnixTimestamp() { return (System.currentTimeMillis() / 1000L); } /** * Gets a readable string for the days/hours/minutes/seconds until a period of time * * @param time * the Unix-TimeStamp to start from * @param delay * the delay from the start point until expiration * * @return the String representation of the time until */ public static String getTimeUntil(final long time, final long delay) { long correctedTime = (time + delay) - getUnixTimestamp(); if (correctedTime <= 0) { return "ERR Time"; } return getTimeUntil(correctedTime); } /** * Gets a readable English {@code String} for the days/hours/minutes/seconds until a period of time * * @param time * the Unix-TimeStamp of (or amount of seconds until) the future time expiration * * @return the String representation of the time until */ public static String getTimeUntil(final long time) { if (time <= 0) { return "ERR Time"; } // How many days left? StringBuilder stringTimeLeft = new StringBuilder(); int[] until = getTimeUntilArray(time); if (until[0] > 0) { stringTimeLeft.append(Integer.toString(until[0])).append(until[0] == 1 ? " day" : " days"); } if (until[1] > 0) { if (stringTimeLeft.length() != 0) { stringTimeLeft.append(until[2] > 0 || until[3] > 0 ? ", " : " and "); } stringTimeLeft.append(Integer.toString(until[1])).append(until[1] == 1 ? " hour" : " hours"); } if (until[2] > 0) { if (stringTimeLeft.length() != 0) { stringTimeLeft.append(until[3] > 0 ? ", " : " and "); } stringTimeLeft.append(Integer.toString(until[2])).append(until[2] == 1 ? " minute" : " minutes"); } if (until[3] > 0) { if (stringTimeLeft.length() != 0) { stringTimeLeft.append(" and "); } stringTimeLeft.append(Integer.toString(until[3])).append(until[3] == 1 ? " second" : " seconds"); } return stringTimeLeft.toString(); } /** * Gets an {@code int[]} representing the number of days, hours, minutes and seconds based on a given Unix Timestamp<br/> * Useful for processing the information into a proper localized {@code String} * * @param time * the time in seconds to break down into days, hours, minutes and seconds * * @return an {@code int[4]} as Index 0 = days, 1 = hours, 2 = minutes, and 3 = seconds including zeros */ public static int[] getTimeUntilArray(final long time) { int[] toRet = new int[]{ 0, 0, 0, 0 }; if (time <= 0) { return toRet; } long temp = time; long conversion = TimeUnit.DAYS.toSeconds(1); if (temp >= conversion) { int days = (int) Math.floor(temp / conversion); temp -= conversion * days; toRet[0] = days; } conversion = TimeUnit.HOURS.toSeconds(1); if (temp >= conversion) { int hours = (int) Math.floor(temp / conversion); temp -= conversion * hours; toRet[1] = hours; } conversion = TimeUnit.MINUTES.toSeconds(1); if (temp >= conversion) { int minutes = (int) Math.floor(temp / conversion); temp -= conversion * minutes; toRet[2] = minutes; } toRet[3] = (int) temp; return toRet; } /** * Gets this class's version number * * @return the class version */ public static float getClassVersion() { return classVersion; } }