• Java中日期格式化的实现算法


    package com.study.test;
    
    import java.io.Serializable;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    /**
     * 实现Java中日期的简单格式化,支持以下字段:
     * yyyy:年
     * MM:月
     * dd:日
     * hh:1~12小时制(1-12)
     * HH:24小时制(0-23)
     * mm:分
     * ss:秒
     * S:毫秒
     * E:星期几
     * a: 上午/下午
     */
    public class DateFormatter implements Serializable {
    
        private static Map<Character, Integer> tokenFieldMap = new HashMap<>();
        private static final int NO_LENGTH = 1000;            //不用自动补0的属性,例如毫秒
        private static final int LOCALE = NO_LENGTH + 1000;  //用Locale获取值的属性,例如星期
    
        //tokenFieldMap,将字符与Calendar中的field对应
        static {
            tokenFieldMap.put('y', Calendar.YEAR);
            tokenFieldMap.put('M', Calendar.MONTH);
            tokenFieldMap.put('d', Calendar.DATE);
            tokenFieldMap.put('h', Calendar.HOUR);
            tokenFieldMap.put('H', Calendar.HOUR_OF_DAY);
            tokenFieldMap.put('m', Calendar.MINUTE);
            tokenFieldMap.put('s', Calendar.SECOND);
            tokenFieldMap.put('a', Calendar.AM_PM + LOCALE);
            tokenFieldMap.put('S',Calendar.MILLISECOND + NO_LENGTH);
            tokenFieldMap.put('E',Calendar.DAY_OF_WEEK + LOCALE);
        }
    
        private static class Token implements Serializable {
            int field;   // Calendar中的field对应
            int length; // 自动补0的长度
    
            public Token(int field, int length) {
                this.field = field;
                this.length = length;
            }
        }
    
        //解析出的token,可能是token或者是String
        private List<Object> tokens;
    
        private String format;
    
        public DateFormatter(String format) {
            this.format = format;
            parseTokens();
        }
    
        public String getFormat() {
            return format;
        }
    
        public String format(Date date){
            if(date == null){
                throw new IllegalArgumentException("null argument!");
            }
            StringBuilder sb = new StringBuilder();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            for(Object token : tokens){
                if(token instanceof Token){
                    token2String(sb,(Token)token,calendar);
                }else{
                    sb.append(token);
                }
            }
            return sb.toString();
        }
    
        private void parseTokens() {
            tokens = new ArrayList<>();
            StringBuilder temp = new StringBuilder();
            for (int i = 0; i < format.length(); i++) {
                char c = format.charAt(i);
                Integer field = tokenFieldMap.get(c);
                if (field != null) {
                    checkStr(temp);
                    if(field < NO_LENGTH){
                        int num = 1;
                        while (i < format.length() - 1 && format.charAt(i + 1) == c) {
                            i++;
                            num++;
                        }
                        tokens.add(new Token(field, num));
                    }else{
                        tokens.add(new Token(field, 0));
                    }
                }else{
                    temp.append(c);
                }
            }
            checkStr(temp);
        }
    
        private void checkStr(StringBuilder temp) {
            if (temp.length() > 0) {
                tokens.add(temp.toString());
                temp.setLength(0);
            }
        }
    
        @SuppressWarnings("MagicConstant")
        private void token2String(StringBuilder sb, Token token, Calendar calendar){
            int field = token.field;
            if(field > LOCALE){
                sb.append(calendar.getDisplayName(field  - LOCALE,Calendar.SHORT,Locale.getDefault()));
            }else if(field > NO_LENGTH){
                sb.append(calendar.get(field - NO_LENGTH));
            }else{
                int val = calendar.get(field);
                if(field == Calendar.MONTH){
                    val++;  //如果是月,取出的范围是0-11,需要加一
                }
                String value = String.valueOf(val);
                if(value.length() > token.length){
                    if(token.field == Calendar.YEAR){       //如果是年,才截取,比如2018可以截取成18年,小时分钟不能截取
                        sb.append(value.substring(value.length() - token.length));
                    }else{
                        sb.append(value);
                    }
                }else{
                    for(int i=0;i<token.length - value.length();i++){   //根据length自动补0
                        sb.append('0');
                    }
                    sb.append(value);
                }
            }
        }
    
    
    
        public static void main(String[] args)throws Exception {
            String fmt = "yy-M-dd a h:m:s E";
            Date date = new Date();
    
            DateFormatter formatter = new DateFormatter(fmt);
            String result = formatter.format(date);
            System.out.println(result);
    
    
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(fmt);
            System.out.println(simpleDateFormat.format(date));
    
            //性能测试
            long t1 = System.currentTimeMillis();
            for(int i=0;i<30000;i++){
                simpleDateFormat.format(new Date(System.currentTimeMillis() + i * 3000 ));
            }
            long t2 = System.currentTimeMillis();
            for(int i=0;i<30000;i++){
                formatter.format(new Date(System.currentTimeMillis() + i * 3000));
            }
            long t3 = System.currentTimeMillis();
    
            System.out.println("formatter cost : " + (t3 - t2));
            System.out.println("java format cost : " + (t2 - t1));
    
        }
    }
  • 相关阅读:
    .OBJ est1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
    线程详细剖析(四)
    线程详细剖析(三)
    线程详细剖析(二)
    线程详细剖析(一)
    CAN总线相关的几个gitlab代码
    进程详细剖析(三)
    C++实现多级排序
    C/C++读写二进制文件
    C++11新特性
  • 原文地址:https://www.cnblogs.com/xcr1234/p/9657042.html
Copyright © 2020-2023  润新知