zoukankan      html  css  js  c++  java
  • Java时间格式Date和String互相转换

    一 常用方案:SimpleDateFormat

    public class TimeUtils {
        public static String formatDate(Date date) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(date);
        }
    
        public static Date parse(String strDate) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                return sdf.parse(strDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }

    二 出现的问题

    每次调用方都要new SimpleDateFormat(),每次处理一个时间信息的时候,就需要创建一个SimpleDateFormat实例对象,然后再丢弃这个对象。大量的对象就这样被创建出来,占用大量的内存和 jvm空间

    于是 那我就创建一个静态的simpleDateFormat实例

    public class TimeUtils {
        private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
        public static String formatDate(Date date) {
            return sdf.format(date);
        }
    
        public static Date parse(String strDate) {
            try {
                return sdf.parse(strDate);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }

    但是问题是:线程不安全,在format方法里,有这样一段代码:

    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        calendar.setTime(date);
        boolean useDateFormatSymbols = useDateFormatSymbols();
        for (int i = 0; i < compiledPattern.length; ) {
            int tag = compiledPattern[i] >>> 8;
            int count = compiledPattern[i++] & 0xff;
            if (count == 255) {
                count = compiledPattern[i++] << 16;
                count |= compiledPattern[i++];
            }
            switch (tag) {
            case TAG_QUOTE_ASCII_CHAR:
                toAppendTo.append((char)count);
                break;
            case TAG_QUOTE_CHARS:
                toAppendTo.append(compiledPattern, i, count);
                i += count;
                break;
            default:
                subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
                break;
            }
        }
        return toAppendTo;
    }
    calendar不是方法局部变量而是SimpleDateFormat类的全局变量,而这就是引发问题的根源。想象一下,在一个多线程环境下,有两个线程持有了同一个SimpleDateFormat的实例,分别调用format方法:
      线程1调用format方法,改变了calendar这个字段。
      中断来了。
      线程2开始执行,它也改变了calendar。
      又中断了。
      线程1回来了,此时,calendar已然不是它所设的值,而是走上了线程2设计的道路。如果多个线程同时争抢calendar对象,则会出现各种问题,时间不对,线程挂死等等。
      分析一下format的实现,我们不难发现,用到成员变量calendar,唯一的好处,就是在调用subFormat时,少了一个参数,却带来了这许多的问题。其实,只要在这里用一个局部变量,一路传递下去,所有问题都将迎刃而解。

    三 解决办法:

    1  SimpleDateFormat作为线程局部变量来使用。2使用对象锁,代码如下。3使用jodaTime(推荐)

    public class TimeUtils {
        private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        public static String formatDate(Date date) {
         	 synchronized(sdf){
             return sdf.format(date);
           }
       }
        public static Date parse(String strDate) {
     		synchronized(sdf){
             try {
                 return sdf.parse(strDate);
             } catch (ParseException e) {
                 e.printStackTrace();
             }
             return null;
    		}
        }

    四 jodaTime使用:

    public class TimeUtils {
        public static String formatDate(Date date) {
            DateTime dateTime = new DateTime(date);
            String formatStr = "yyyy-MM-dd HH:mm:ss";
            return dateTime.toString(formatStr);
        }
        public static Date parse(String strDate) {
            DateTimeFormatter dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
            DateTime dateTime = DateTime.parse(strDate, dateTimeFormat);
            dateTime = dateTime.plusDays(1);
            return dateTime.toDate();
        }
    }
  • 相关阅读:
    Django的model form
    Django之验证码
    ajax获取跨域数据
    js+css模仿打字效果
    CSS自定义消息提示
    CSS画各种二维图形
    最简单的动态进度条
    利用javascript(自定义事件)记录尺寸可变元素的尺寸变化过程
    超级简单的利用javascript实现文件拖拽事件
    javascript 公历与农历相互转换工具类
  • 原文地址:https://www.cnblogs.com/wanghongsen/p/9073108.html
Copyright © 2011-2022 走看看