[Java/日期/时间/时区] Java 时间的转换与处理:DateTimeUtils
1 概述:Java 时间的转换与处理
深入理解:Date / Calendar / Timestamp / TimeZone
java.util.Date/java.sql.Timestamp: 基于时间戳(Long)构建,与时区无关java.util.Calendar: 基于时间字符串(String)构建,与时区强依赖java.text.SimpleDateFormat: 与时区强依赖java.util.TimeZone: 时区对象
Z 最佳实践
DateTimeUtils
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* @updateTime 2025-09-10 23:28
* @description
* @reference-doc
* [1] java 不同时区转换 - CSDN - https://blog.csdn.net/qq_41344974/article/details/125505290
*/
public class DatetimeUtils {
private final static Logger logger = LoggerFactory.getLogger(DatetimeUtils.class);
/** 毫秒级时间字符串 millisecond time format **/
public final static String MILLISECOND_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
public final static String MILLISECOND_TIME_WITH_NUMBER_FORMAT = "yyyyMMddHHmmssSSS";
/**
* 时区ID
* @sample-values 可选值
* "Asia/Shanghai" / "UTC" / "GMT" / ...
* @note
* "Asia/Shanghai" = "CST" (China Standard Time) = GMT+8 = UTC+8
*/
public final static String zoneId = "UTC";
//public final static TimeZone time
public static String calendarToString(Calendar calendar, String format, TimeZone targetTimeZone){
SimpleDateFormat sdf = new SimpleDateFormat(format); //such as: "yyyy-MM-dd"
sdf.setTimeZone( targetTimeZone );
return sdf.format(calendar.getTime());//时间戳转指定时区的时间字符串
}
public static Calendar stringToCalendar(String dateStr,String format, TimeZone timeZone) throws ParseException {
SimpleDateFormat sdf= new SimpleDateFormat(format); //such as:"yyyy-MM-dd"
sdf.setTimeZone( timeZone );
Date date = sdf.parse(dateStr);
return dateToCalendar(date, timeZone);
}
/**
* 时间戳 转 Date
* @note
* 1. {@link Date } 底层存储与维护的是 long (时间戳)
* 2. 基于第1点,未涉及时区
* @param time 13位的毫秒级时间戳 eg: 1503544630000L
* @return
*/
public static Date longToDate(long time){
return new Date(time);
}
public static Calendar longToCalender(long time, TimeZone timeZone){
return dateToCalendar( longToDate(time), timeZone );
}
public static Long calenderToLong(Calendar calendar){
return calendarToTimestamp(calendar).getTime();
}
/**
*
* @param time
* eg:
* 1665211423751L
* @param format
* eg:
* "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
* @return
* eg:
* "2022-10-08T14:43:43.751Z"
*/
public static String longToString(long time, String format, TimeZone timeZone){
return calendarToString( longToCalender(time, timeZone), format, timeZone );
}
/**
*
* @param datetimeStr 当前应用的时间字符串
* eg:
* "2022-10-06 11:49:00"
* "2022-10-06 11:49"
* "2022-10-08T07:01:40.751Z"
* @param format
* eg:
* "yyyy-MM-dd hh:mm:ss"
* "yyyy-MM-dd hh:mm"
* "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" | T代表可替换的任意字符, Z 代表时区
* @param timeZone [选填参数] 允许为 null
* 可选值有:
* "UTC" / "Asia/Shanghai" / "GMT" / "GMT+08:00" / ...
* @return
* eg:
* 1665028140000L
* 1665028140000L
* 1665212500751L [timeZone=UTC] 1665183700751L [timeZone=null]
* @reference-doc
* [1] java 不同时区转换 - CSDN - https://blog.csdn.net/qq_41344974/article/details/125505290
*/
public static long stringToLong(String datetimeStr, String format, String timeZone) {
SimpleDateFormat formatSDF = new SimpleDateFormat(format);// such as "yyyyMMddhhmmss"
//new SimpleDateFormat(format, Locale.getDefault());// such as "yyyyMMddhhmmss"
if(! StringUtils.isEmpty(timeZone) ){
formatSDF.setTimeZone(TimeZone.getTimeZone(timeZone));
}
Date date = null;
try {
date = formatSDF.parse(datetimeStr);
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return -1;
}
public static long stringToLong(String datetimeStr, String format, TimeZone timeZone) {
return stringToLong(datetimeStr, format, timeZone);
}
public static String dateToString(Date date, String format, TimeZone timeZone){
SimpleDateFormat sdf= new SimpleDateFormat(format); //such as:"yyyy-MM-dd"
sdf.setTimeZone(timeZone);
return sdf.format(date);
}
public static Date stringToDate(String dateStr, String formatOfStr, TimeZone timeZone) throws ParseException {
//dateStr such as :"2018-11-4"
SimpleDateFormat sdf = new SimpleDateFormat(formatOfStr);//such as:"yyyy-MM-dd"
sdf.setTimeZone( timeZone );
return sdf.parse(dateStr);
}
/**
* Date 转 Calendar
* @note
* 1. 此转换过程,因涉及 {@link Calendar } 涉及时区
* @param date
* @return
*/
@Deprecated
public static Calendar dateToCalendar(Date date){
Calendar calendar = Calendar.getInstance();//等效于: createCalendar(TimeZone.getDefault(), Locale.getDefault(Category.FORMAT));
calendar.setTime(date);
return calendar;
}
public static Calendar dateToCalendar(Date date, TimeZone timeZone){
Calendar calendar = Calendar.getInstance( timeZone );//createCalendar(TimeZone.getDefault(), Locale.getDefault(Category.FORMAT));
calendar.setTime(date);
return calendar;
}
public static Date calendarToDate(Calendar calendar){
Date date = calendar.getTime();
return date;
}
public static Timestamp stringToTimestamp(String dateStr,String dateFormat, TimeZone timeZone) throws ParseException {
//dateStr such as:"2019-1-14 08:11:00"
Calendar calendar = stringToCalendar(dateStr, dateFormat, timeZone);
Timestamp timestamp = new Timestamp( calendar.getTimeInMillis() );
//Timestamp timestamp = Timestamp.valueOf(dateStr);
return timestamp;
}
public static String timestampToString(Timestamp timestamp, String format, TimeZone timeZone){
SimpleDateFormat sdf= new SimpleDateFormat(format);//such as:"yyyy-MM-dd"
sdf.setTimeZone( timeZone );
return sdf.format(timestamp);
}
public static Timestamp dateToTimestamp(Date date){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timestamp timestamp = new Timestamp( date.getTime() );
//Timestamp timestamp = Timestamp.valueOf(df.format(date));
return timestamp;
}
public static Calendar timestampToCalendar(Timestamp timestamp, TimeZone timeZone){
Calendar calendar = Calendar.getInstance(timeZone);
calendar.setTime(timestamp);
return calendar;
}
public static Timestamp calendarToTimestamp(Calendar calendar){
return dateToTimestamp( calendarToDate(calendar) );
}
public static String millisecondToDateString(long ms){
Integer ss = 1000;
Integer mi = ss * 60;
Integer hh = mi * 60;
Integer dd = hh * 24;
Long day = ms / dd;
Long hour = (ms - day * dd) / hh;
Long minute = (ms - day * dd - hour * hh) / mi;
Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
StringBuffer sb = new StringBuffer();
if(day >= 0) {
sb.append(day+"day");
}
if(hour >= 0) {
sb.append(hour+"hour");
}
if(minute >= 0) {
sb.append(minute+"minute");
}
if(second >= 0) {
sb.append(second+"second");
}
return sb.toString();
}
/**
* 纳秒数转毫秒级时间戳
* @param targetNanoTime
* eg: long targetNanoTime = System.nanoTime(); // 获取当前时间的 nano time,例如 : 87277522042200
* @return
*/
public static long nanoTimeToMillisTimestamp(long targetNanoTime){
//待转换的纳秒时间(targetNanoTime)
//long targetNanoTime = System.nanoTime(); // 获取当前时间的 nano time,例如 : 87277522042200
//获取当前的毫秒数(currentTimeMillis) 和 纳秒数(currentNanoTime)
long currentTimeMillis = System.currentTimeMillis();//例如: 1733985453227
long currentNanoTime = System.nanoTime();//例如 : 87277522044200
//计算 currentNanoTime 与 targetNanoTime 的差值(nanoTimeDiff)
long nanoTimeDiff = currentNanoTime - targetNanoTime;//例如: 2000
// 利用 currentNanoTime 和 nanoTimeDiff ,向前推算出 targetNanoTime当时对应的毫秒级时间戳
long targetMillisTime = currentTimeMillis - ( nanoTimeDiff / 1000000L);//13位的毫秒级时间戳,例如: 1733985453227
//Date date = new Date(targetMillisTime); // 创建日期对象
//System.out.println("date : " + date.toString());//例如: date : Thu Dec 12 14:37:33 CST 2024
return targetMillisTime;
}
}
Y 推荐文献
- 是不是Date对象里存了【年月日时分秒】呢?不是的,【Date对象】里存的只是一个【long】型的变量,其值为UTC+0时区、自【1970年1月1日0点】至Date对象所记录时刻经过的毫秒数
- 时间戳与 Date对象的转换: Date date = new Date(1503544630000L); Long timestamp = date.getTime();
- 时区:全球分为24个时区,相邻时区时间相差1个小时。
X 参考文献
本文作者:
千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号