
正文
Java常用类Date、Calendar、SimpleDateFormat详解
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
Date类
java.util 包提供了 Date 类来封装当前的日期和时间,Date 类提供两个构造函数来实例化 Date 对象
- 第一个构造函数使用当前日期和时间来初始化对象 Date( )
- 第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数 Date(long millisec)
package com.yyx.util;
import java.util.Date;
/**
* 日期时间工具类
*
* @author yyx 2018年6月25日
*/
public class DateUtil {
public static void main(String[] args) {
testDate();
}
/**
* Date类的其他方法都已过时,被替代
*/
public static void testDate() {
Date date=new Date();
System.out.println(date.toString());
//getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数
long currentTime=date.getTime();
System.out.println(currentTime);
//设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点
date.setTime(currentTime+1530367288365L);
System.out.println(date.toString());
long time=System.currentTimeMillis();
Date dateAnother=new Date(time);
System.out.println(dateAnother.toString());
}
}
Calendar类
Calendar是一个抽象类,不能直接实例化,但是Calendar类提供一个工厂方法,即getInstance来创建一个Calendar实例
package com.yyx.util;
import java.util.Calendar;
import java.util.Date;
/**
* 日期时间工具类
*
* @author yyx 2018年6月25日
*/
public class DateUtil {
public static void main(String[] args) {
TestCalendar();
}
public static void TestCalendar() {
Calendar calendar = Calendar.getInstance();
// 获取年份
int year = calendar.get(Calendar.YEAR);
// 获取月,这里需要需要月份的范围为0~11,因此获取月份的时候需要+1才是当前月份值
int month = calendar.get(Calendar.MONTH) + 1;
// 获取日
int day = calendar.get(Calendar.DAY_OF_MONTH);
// 获取时
// int hour = calendar.get(Calendar.HOUR);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // 24小时表示
// 获取分
int minute = calendar.get(Calendar.MINUTE);
// 获取秒
int second = calendar.get(Calendar.SECOND);
// 星期,英语国家星期从星期日开始计算
int weekday = calendar.get(Calendar.DAY_OF_WEEK) - 1;
System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + " 星期" + weekday);
//将给定的日历字段设置为给定值
calendar.set(Calendar.YEAR, 2020);
calendar.set(Calendar.MONTH, 7);
System.out.println(calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH)+1) + "-" + day + " " + hour + ":" + minute + ":" + second + " 星期" + weekday);
//根据日历的规则,为给定的日历字段添加或减去指定的时间量
calendar.add(Calendar.YEAR, 2);
System.out.println(calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH)+1) + "-" + calendar.get(Calendar.DAY_OF_MONTH));
//返回一个表示此 Calendar 时间值(从历元至现在的毫秒偏移量)的 Date 对象
Date date=calendar.getTime();
System.out.println(date.toString());
//使用给定的 Date 设置此 Calendar 的时间
Date dateAnother=new Date();
calendar.setTime(dateAnother);
System.out.println(calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH)+1) + "-" + calendar.get(Calendar.DAY_OF_MONTH));
}
}
SimpleDateFormat类
SimpleDateFormat 是一个以与语言环境相关的方式来格式化和分析日期的具体类。它允许进行格式化(日期 -> 文本)、分析(文本 -> 日期)和规范化
package com.yyx.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期时间工具类
*
* @author yyx 2018年6月25日
*/
public class DateUtil {
public static void main(String[] args) {
testSimpleDateFormat();
}
public static void testSimpleDateFormat() {
//format() 将给定的 Date 格式化为日期/时间字符串
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
Date date=new Date();
System.out.println(simpleDateFormat.format(date));
String dateString = "2009-08-02 13:43:00";
SimpleDateFormat df =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//parse() 解析字符串的文本,生成 Date
try {
System.out.println(df.parse(dateString));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
SimpleDateFormat日期格式是不同步的。建议为每个线程创建独立的格式实例。如果多个线程同时访问一个格式,则它必须是外部同步的
解决方法
1、需要的时候创建新实例
说明: 在需要用到 SimpleDateFormat 的地方新建一个实例,不管什么时候,将有线程安全问题的对象由共享变为 局部私有 都能避免多线程问题,不过也加重了创建对象的负担。在一般情况下,这样其实对性能影响比不是很明显的。
2、使用同步:同步 SimpleDateFormat 对象
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateSyncUtil {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String formatDate(Date date) throws ParseException {
synchronized(sdf) {
return sdf.format(date);
}
}
public static Date parse(String strDate) throws ParseException {
synchronized(sdf) {
return sdf.parse(strDate);
}
}
}
说明: 当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要 block 等待,多线程并发量大的时候会对性能有一定的影响
3、使用 ThreadLocal
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ConcurrentDateUtil {
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static Date parse(String dateStr) throws ParseException {
return threadLocal.get().parse(dateStr);
}
public static String format(Date date) {
return threadLocal.get().format(date);
}
}
说明: 使用 ThreadLocal, 也是将共享变量变为独享,线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下,一般推荐使用这种方法
4、Java 8 中的解决办法
Java 8 提供了新的日期时间 API,其中包括用于日期时间格式化的 DateTimeFormatter,它与 SimpleDateFormat 最大的区别在于:DateTimeFormatter 是线程安全的,而 SimpleDateFormat 并不是线程安全







