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 并不是线程安全
最新文章
- No module named django.core
- SQL,根据不同条件拼接不同SQL,非if拼接 改为SQL where形式
- moss2003 sp3补丁安装
- 今天做项目用到框架,关于angual,然后自己整理了一番,自己上网也看了看。
- Android下的数据储存方式( 二)
- HTML5文件系统API和资料整理
- BZOJ1012——[JSOI2008]最大数maxnumber
- Linux上在同一端口上共享SSH与HTTPS的工具:SSLH
- (转)12款开源JavaScript库
- poj2331 (IDA*)
- Pandas系列(十二)-可视化详解
- 在Python程序中的进程操作,multiprocess.Process模块
- vue 常用手册
- 微信小程序<; 3 >; ~ 微信小程序开源项目合集
- pthread编译时报错的解决方法
- [CoreOS 转载] CoreOS实践指南(三):系统服务管家Systemd
- RxJava &;&; Agera 从源码简要分析基本调用流程(2)
- 實現多个checkbox單選功能(转)
- tyvj 1055 沙子合并 区间dp经典模型,石子合并
- MPI编程指南
热门文章
- 转:css:Position
- vsftpd 自动安装脚本
- 如何利用hibernate3解决数据库丢失更新问题?
- erlang的token值加解密
- HDU 5338(ZZX and Permutations-用线段树贪心)
- delphi 颜色 引用http://www.cnblogs.com/del/archive/2008/02/19/1073568.html
- 【BZOJ4241】历史研究 分块
- 基于EasyNVR二次开发实现业务需求:用户、权限、设备管理
- static 不被实例调用
- typescript import 全局node_modules报错