这篇文章不是系统的学习,是阅读一些文章,然后总结汇总的。
一:SimpleDateFormat类
1.介绍
SimpleDateFormat
是一个以国别敏感的方式格式化和分析数据的具体类。 它允许格式化 (date -> text)、语法分析 (text -> date)和标准化。
SimpleDateFormat
允许以为日期-时间格式化选择任何用户指定的方式启动。
但是,希望用 DateFormat
中的 getTimeInstance
、 getDateInstance
或 getDateTimeInstance
创建一个日期-时间格式化程序。 每个类方法返回一个以缺省格式化方式初始化的日期/时间格式化程序。 可以根据需要用 applyPattern
方法修改格式化方式。
2.继承关系
java.lang.Object
|
+----java.text.Format
|
+----java.text.DateFormat
|
+----java.text.SimpleDateFormat
3.语法
G 年代标志符
y 年
M 月
d 日
h 时 在上午或下午 (1~12)
H 时 在一天中 (0~23)
m 分
s 秒
S 毫秒
E 星期
D 一年中的第几天
F 一月中第几个星期几
w 一年中第几个星期
W 一月中第几个星期
a 上午 / 下午 标记符
k 时 在一天中 (1~24)
K 时 在上午或下午 (0~11)
z 时区
二:案例一
1.format
日期对象产生日期字符串。
package com.cao.it; import java.text.SimpleDateFormat;
import java.util.Date; public class Test1 {
public static void main(String[] args) {
SimpleDateFormat myFmt = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
SimpleDateFormat myFmt1 = new SimpleDateFormat("yy/MM/dd HH:mm");
SimpleDateFormat myFmt2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 等价于now.toLocaleString()
SimpleDateFormat myFmt3 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E");
SimpleDateFormat myFmt4 = new SimpleDateFormat("一年中的第 D 天 一年中第w个星期 一月中第W个星期 在一天中k时 z时区"); Date now = new Date(); System.out.println(myFmt.format(now));
System.out.println(myFmt1.format(now));
System.out.println(myFmt2.format(now));
System.out.println(myFmt3.format(now));
System.out.println(myFmt4.format(now)); System.out.println("======"); System.out.println(now.toGMTString());
System.out.println(now.toLocaleString()); //这个方法产生的效果和上面的一样,不建议使用这个方法
System.out.println(now.toString());
}
}
2.效果
3.对上面的一个补充
format后返回的是String。
package com.cao.it;
import java.text.SimpleDateFormat;
import java.util.Date; public class Test2 {
public static String toLongDateString(Date dt){
SimpleDateFormat myFmt=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E ");
return myFmt.format(dt);
} public static String toLongTimeString(Date dt){
SimpleDateFormat myFmt=new SimpleDateFormat("HH mm ss SSSS");
return myFmt.format(dt);
} public static void main(String[] args) {
Date now=new Date();
System.out.println(toLongDateString(now));
System.out.println(toLongTimeString(now));
}
}
4.效果
三:案例二
1.parse
字符串中提取日期。
package com.cao.it; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; class Test3 {
public static void main(String[] args) throws Exception {
String str = "2009-02-15 09:21:35.345";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒SSS毫秒"); //必须使用相同的格式才好进行解析
Date date = sdf1.parse(str); // 提取格式中的日期
System.out.println("转换之前的日期:" + date); String newStr1 = sdf1.format(date); // 改变格式
System.out.println("转换之后的日期:" + newStr1); String newStr2 = sdf2.format(date); // 改变格式
System.out.println("转换之后的日期:" + newStr2);
}
}
2.效果
四:Calendar
1.程序
package com.cao.it; import java.util.Calendar; public class Test4 {
public static void main(String[] args) {
Calendar date=Calendar.getInstance();
int day=date.get(Calendar.HOUR_OF_DAY ); //得到24小时机制的
int hour=date.get(Calendar.HOUR); //得到12小时机制的
System.out.println(day);
System.out.println(hour);
}
}
2.效果
五:安全问题
参考文档:https://www.cnblogs.com/peida/archive/2013/05/31/3070790.html
1.问题
DateFormat 和 SimpleDateFormat 类不都是线程安全的,在多线程环境下调用 format() 和 parse() 方法应该使用同步代码来避免问题。
2.下面是解决方法一
在需要用到SimpleDateFormat 的地方新建一个实例,不管什么时候,将有线程安全问题的对象由共享变为局部私有都能避免多线程问题,不过也加重了创建对象的负担。
在一般情况下,这样其实对性能影响比不是很明显的。
package com.cao.it; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class Test5 {
/**
* 两个静态方法
* 在要使用SimpleDateFormat的时候才创建类对象
*/
public static String formatDate(Date date,String parent)throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(parent);
return sdf.format(date);
} public static Date parse(String strDate,String parent) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(parent);
return sdf.parse(strDate);
}
/**
* 测试主类
*/
public static void main(String[] args) throws ParseException {
String parent="yyyy-MM-dd HH:mm:ss";
//
Date date=new Date();
String dateStr=formatDate(date,parent);
System.out.println(dateStr);
//
String strDate="2017-12-27 21:56:36";
Date mydate=parse(strDate, parent);
System.out.println(date);
System.out.println(date.toLocaleString()); }
}
3.效果
4.下面是解决方法二
当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,多线程并发量大的时候会对性能有一定的影响。
我认为,这个不适合写成工具类,因为sdf中的格式被固定了。
package com.cao.it; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class Test6 {
private static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String format(Date date) {
synchronized (sdf) {
return sdf.format(date);
}
}
public static Date parse(String dateStr) throws ParseException {
synchronized(sdf) {
return sdf.parse(dateStr);
}
}
/**
* 测试主方法
*/
public static void main(String[] args) {
Date date=new Date();
String datestr=format(date);
System.out.println(datestr);
}
}
5.下面是解决方法三
使用ThreadLocal, 也是将共享变量变为独享,线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下,一般推荐使用这种方法。
package com.cao.it; import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class Test7 {
// private static final String date_format = "yyyy-MM-dd HH:mm:ss";
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(); /**
*获取SimpleDateFormat
*/
public static DateFormat getFormat(String date_format)
{
DateFormat df = threadLocal.get();
if(df==null){
df = new SimpleDateFormat(date_format);
threadLocal.set(df);
}
return df;
} public static String formatDate(Date date,String date_format) throws ParseException {
return getFormat(date_format).format(date);
} public static Date parse(String strDate,String date_format) throws ParseException {
return getFormat(date_format).parse(strDate);
} /**
* 测试主类
* @throws ParseException
*/
public static void main(String[] args) throws ParseException {
Date date=new Date();
String parent="yyyy--mm--dd HH:mm:ss";
String dateStr=formatDate(date, parent);
System.out.println(dateStr); } }
6.效果
7.总结
如果在必要的时候,追求那么一点性能提升的话,可以考虑用方法三,用ThreadLocal做缓存。