/*
* Copyright im.longkaii@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.newgxu.ng.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* A common utility deals with date and time.
*
* @author longkai
* @since 2013-01-13
* @version 0.1
*/
public class DateTime {
/** the ISO datetime pattern: yyyy-MM-dd HH:mm:ss */
public static final String ISO_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
/** the ISO date pattern: yyyy-MM-dd */
public static final String ISO_DATE_PATTERN = "yyyy-MM-dd";
/** the ISO time pattern: HH:mm:ss */
public static final String ISO_TIME_PATTERN = "HH:mm:ss";
/** the regex of the ISO date pattern */
public static final String ISO_TIME_REGEX = "(\\d{2}|\\d):(\\d{2}|\\d):(\\d{2}|\\d)";
/** the regex of the ISO time pattern */
public static final String ISO_DATE_REGEX = "\\d{4}-(\\d{2}|\\d)-(\\d{2}|\\d)";
/** the regex of the ISO datetime pattern */
public static final String ISO_DATE_TIME_REGEX = ISO_DATE_REGEX + " " + ISO_TIME_REGEX;
/** a thread local object that bind a simple data format */
private static ThreadSafeDateFormat threadLocal;
/** a thead-safe date format */
private static SimpleDateFormat dateFormat;
/**
* set up the date format if need format method.
*/
private static void setup() {
if (threadLocal == null) {
threadLocal = new ThreadSafeDateFormat();
}
dateFormat = threadLocal.get();
}
/**
* format the given date to the ISO data-time pattern (yyyy-MM-dd HH:mm:ss)
*
* @param date
* @return
*/
public static String format(Date date) {
if (dateFormat == null) {
setup();
}
return dateFormat.format(date);
}
/**
* parse the given date string as a Date object.
* @param date
* @return Date object.
* @see java.util.Date
* @throws ParseException
*/
public static Date parse(String date) throws ParseException {
if (dateFormat == null) {
setup();
}
if (RegexUtils.matches(date, ISO_TIME_REGEX)) {
// if it only has time, it' ll append the current date.
Date now = new Date();
date = format(now, ISO_DATE_PATTERN) + " " + date;
} else if (RegexUtils.matches(date, ISO_DATE_REGEX)) {
// if it only has date, it' ll append the 00:00:00 time.
date += " 00:00:00";
}
return dateFormat.parse(date);
}
/**
* Does the string can be parsable to a type of string?
* @param str
* @return parsable?
*/
public static boolean parsable(String str) {
if (RegexUtils.contains(str, ISO_DATE_TIME_REGEX)) {
return true;
} else if (RegexUtils.contains(str, ISO_DATE_REGEX)) {
return true;
} else if (RegexUtils.contains(str, ISO_TIME_REGEX)) {
return true;
}
return false;
}
/**
* format the given date to the given pattern
*
* @param date
* @return
*/
public static String format(Date date, String pattern) {
if (dateFormat == null) {
setup();
}
dateFormat.applyPattern(pattern);
try {
return dateFormat.format(date);
} finally {
// we need to remain the default pattern
dateFormat.applyPattern(ISO_DATE_TIME_PATTERN);
}
}
/**
* judge the current system time whether is before or not.
*
* @param calendar the given calendar
* @return if before, true, or false
*/
public static boolean before(Calendar calendar) {
return System.currentTimeMillis() < calendar.getTimeInMillis();
}
/**
* judge the current system time whether is after or not.
*
* @param calendar the given calendar
* @return if before, true, or false
*/
public static boolean after(Calendar calendar) {
return !before(calendar);
}
/**
* judge the current system time whether is before or not.
*
* @param date the given date
* @return if before, true, or false
*/
public static boolean before(Date date) {
return System.currentTimeMillis() < date.getTime();
}
/**
* judge the current system time whether is after or not.
*
* @param date the given date
* @return if before, true, or false
*/
public static boolean after(Date date) {
return !before(date);
}
/**
* judge the current system's time is between the beginline and deadline.
*
* @param beginline
* @param deadline
* @return if in true, or false
*/
public static boolean between(Calendar beginline, Calendar deadline) {
return before(deadline) && after(beginline);
}
/**
* judge the current system's time is between the beginline and deadline.
*
* @param beginline
* @param deadline
* @return if in true, or false
*/
public static boolean between(Date beginline, Date deadline) {
return before(deadline) && after(beginline);
}
/**
* obtain the millis time gap between current system's time, always return positive!
* @param date the given date
* @return the positive millis gap
*/
public static long millisGap(Date date) {
long now = System.currentTimeMillis();
long gap = now - date.getTime();
return gap > 0 ? gap : -gap;
}
/**
* 将绝对时间转换为相对时间,相对于当前的系统时间。
* @param time
* @return 相对时间
*/
public static String getRelativeTime(long time) {
long now = System.currentTimeMillis();
long offset = now - time;
// 如果大于当前时间,那么你就穿越了-.-
if (offset < 0) {
throw new IllegalArgumentException("你穿越了吗?");
}
// 秒杀- -
long second = 1000;
if (offset < second * 10) {
return "刚刚~";
}
// xx秒前
long minute = 60 * second;
if (offset < minute) {
return (offset / second) + "秒前";
}
// xx分钟前
long hour = minute * 60;
if (offset < hour) {
return (offset / minute) + "分钟前";
}
// xx小时前
long day = hour * 24;
if (offset < day) {
return (offset / hour) + "小时前";
}
// xx天前,简单起见,每个月假设都为30天
long month = day * 30;
if (offset < month) {
return (offset / day) + "天前";
}
// xx月前
long year = month * 12;
if (offset < year) {
return (offset / month) + "个月前";
}
// xx年前
return (offset / year) + "年前";
}
/**
* A thread-safe datatime format.
*
* @author longkai
* @since 2013-01-13
* @version 1.0
*/
private static class ThreadSafeDateFormat extends
ThreadLocal<SimpleDateFormat> {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(ISO_DATE_TIME_PATTERN);
}
}
}