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)); } }