java 常用的时间工具类
- java.util.Calender
- java.util.Date 是用于表示一个日期和时间的对象(实际一个long类型的以毫秒表示的时间戳)
- java.time.LocalDateTime
- java.time.LocalDate
- java.time.ZonedDateTime
- java.time.Instant
初始化操作及具体时间的指定:
- data
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:MM:ss");
// 导包的时候要注意不要导成java.sql.Date
Date date = new Date();
System.out.println(sdf.format(date));
System.out.println(date.getYear() + 1900); // 必须加上1900
System.out.println(date.getMonth() + 1); // 0~11,必须加上1
System.out.println(date.getDate()); // 1~31,不能加1
// 转换为String:
System.out.println(date.toString());
// 转换为GMT时区:
System.out.println(date.toGMTString());
// 转换为本地时区:
System.out.println(date.toLocaleString());
}
date设置指定时间的的一些方法目前1.8都不推荐使用了,如下:
- Calender
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 支持四种初始化的方式,可以根据具体的业务,选择合适的方式
Calendar calendar = Calendar.getInstance();
// 清除默认的当前时间设置指定的时间(清除所有)
calendar.clear();
calendar.set(Calendar.YEAR, 2020);
// 设置八表示九月
calendar.set(Calendar.MONTH, 8);
// 其他属性不设置则使用默认值
// 调用getTime使Calender对象转为Date,才做时间处理
System.out.println(sdf.format(calendar.getTime()));
}
LocalDateTime
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 为时间可以具体到秒
LocalDateTime time = LocalDateTime.now();
// 当前时间的加多少分钟,其他属性也是plus开头的,减时间为minus开头的方法
time.plusMinutes(10);
String format = dtf.format(time);
System.out.println(format); //print 2020-10-30 14:22:30
}
LocalDate
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 为时间可以具体到秒
LocalDate time = LocalDate.now();
// 当前时间的加多少分钟,其他属性也是plus开头的,减时间为minus开头的方法(不能支持到小时以后更小的操作)
// 同时 DateTimeFormatter不能指定到小时以后,否则抛出UnsupportedTemporalTypeException异常
time.plusDays(10);
String format = dtf.format(time);
System.out.println(format); //print 2020-10-30 14:22:30
}
ZoneLocalDateTime
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 默认时区,若需特别指定具体的时区时可以ZonedDateTime.now(ZoneId.of("America/New_York")); 用指定时区获取当前时间
ZonedDateTime time = ZonedDateTime.now();
time.plusDays(10);
String format = dtf.format(time);
System.out.println(format);
// 以中国时区获取当前时间:
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
// 转换为纽约时间:
ZonedDateTime zny = now.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(now);
System.out.println(zny);
}
**Instant **
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 这个当前时间戳在java.time中以Instant类型表示,我们用Instant.now()获取当前时间戳,
Instant now = Instant.now();
// 不可格式化
System.out.println(now.getEpochSecond()); // 秒
System.out.println(now.toEpochMilli()); // 毫秒
}
格式化参数说明
- G Era 标志符
- y 年
- M 年中的月份
- w 年中的周数
- W 月中的周数
- D 年中的天数
- d 月中的天数
- F 月份中的星期
- E 星期中的天数
- a Am/pm 标记
- H 一天中的小时数(0-23)
- k 一天中的小时数(1-24
- K am(中午)/pm(下午) 中的小时数(0-11)
- h am(中午)/pm(下午) 中的小时数(1-12)
- m 小时中的分钟数
- s 分钟中的秒数
- S 毫秒
常用的时间格式类(java)
- SimpleDateFormat
- DateTimeFormatter
SimpleDateFormat是一个可变的对象,使用的使用会存在一定线程安全问题。而DateFimeFormatter反之(因为是一个不可变对象,同时只创建一个实例)
初始化方式和简单使用:
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
// 使用DateTimeFormatter,将LocalDateTime转为指定格式的String
System.out.println("dateTimeFormatter ——————>" + dtf.format(now));
Date date = new Date();
System.out.println("simpleDateFormat ——————>" + sdf.format(date));
String str = "2020-10-30 15:04:19";
LocalDateTime specified = LocalDateTime.parse(str,dtf);
Date parse = sdf.parse(str);
}
SimpleDateFormat线程安全的问题的bug复现
//(1)创建单例实例
static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws ParseException {
//(2)创建多个线程,并启动
for (int i = 0; i < 20; ++i) {
Thread thread = new Thread(new Runnable() {
public void run() {
try {//(3)使用单例日期实例解析文本
System.out.println(sdf.parse("2020-10-30 15:26:22"));
} catch (ParseException e) {
e.printStackTrace();
}
}
});
thread.start();//(4)启动线程
}
}
通过运行的结果可知,近三分之一的都报错了。可以通过改造使其达到线程安全(过程繁琐,不如之间用DateTimeFormatter)。
改造为线程安全的SimpleDateFormat如下:
// 用于存放不同模式的SimpleDateFormat
private static Map<String, ThreadLocal<SimpleDateFormat>> containerMap = new HashMap<>();
private static final ReentrantLock lock = new ReentrantLock();
/**
* 功能描述 根据不同格式化要求,返回不同的安全的SimpleDateFormat对象
*
* @param pattern
* @return SimpleDateFormat对象
*/
public static SimpleDateFormat getSimpleDateFormat(final String pattern) {
ThreadLocal<SimpleDateFormat> local = containerMap.get(pattern);
final ReentrantLock creatLock = lock;
if (local == null) {
// 加锁操作
creatLock.lock();
try {
local = containerMap.get(pattern);
if (local == null) {
local = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(pattern);
}
};
}
} finally {
creatLock.unlock();
}
}
return local.get();
}
性能对比
使用默认的性能如下:
优化后性能如下:
以上为java提供时间类的简单使用总结。