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

Java中日期格式化的实现算法的更多相关文章

  1. 震惊!java中日期格式化的大坑!

    前言 我们都知道在java中进行日期格式化使用simpledateformat.通过格式 yyyy-MM-dd 等来进行格式化,但是你知道其中微小的坑吗? yyyy 和 YYYY 示例代码 @Test ...

  2. Java中日期格式化YYYY-DD的坑

    写这篇博文是记录下跨年的bug.去年隔壁组的小伙伴就是计算两个日期之间间隔的天数,因为跨年的原因计算有误. 当时测试组的小姐姐也没有模拟出来这种场景,导致上生产环境直接影响线上的数据. 今天逛技术论论 ...

  3. Java中日期格式化SimpleDateFormat类包含时区的处理方法

    1.前言 需要把格式为“2017-02-23T08:04:02+01:00”转化成”23-02-2017-T15:04:02“格式(中国时区为+08:00所以是15点),通过网上查找答案,发现没有我需 ...

  4. Java基础-日期格式化DateFormat类简介

    Java基础-日期格式化DateFormat类简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.DateFormat类概述 DateFormat 是日期/时间格式化子类的抽象 ...

  5. java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)

    转载地址:http://www.devba.com/index.php/archives/4581.html java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明); ...

  6. (转)java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)

    java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明);部分资料参考网络资源 1. java向MySQL插入当前时间的四种方式 第一种:将java.util.Date ...

  7. java中日期常用

    Java中日期的几种常见操作 —— 取值.转换.加减.比较 Java 的开发过程中免不了与 Date 类型纠缠,准备总结一下项目经常使用的日期相关操作,JDK 版本 1.7,如果能够帮助大家节约那么几 ...

  8. JAVA中日期 yyyy-MM-dd HH:mm:ss和yyyy-MM-dd hh:mm:ss的区别

    JAVA中日期 yyyy-MM-dd HH:mm:ss和yyyy-MM-dd hh:mm:ss的区别 : HH:24小时制 hh:12小时制 package time; import java.tex ...

  9. 聊聊 Java 中日期的几种常见操作 —— 取值、转换、加减、比较

    Java 的开发过程中免不了与 Date 类型纠缠,准备总结一下项目经常使用的日期相关操作,JDK 版本 1.7,如果能够帮助大家节约那么几分钟起身活动一下,去泡杯咖啡,便是极好的,嘿嘿.当然,我只提 ...

随机推荐

  1. 6月5日 python学习总结 jQuery (二)

    1. 操作样式     对CSS类的操作: addClass();// 添加指定的CSS类名. removeClass();// 移除指定的CSS类名. hasClass();// 判断样式存不存在 ...

  2. PowerSploit的使用

    Invoke-Mimikatz(依赖管理员) Import-Module .\invoke-mimikatz.ps1 Invoke-Mimikatz –DumpCreds 使用Invoke-Mimik ...

  3. WIFI-Pumpkin无线钓鱼渗透

    WIFI-Pumpkin无线钓鱼渗透 描述 WiFi-Pumpkin是一款专用于无线环境渗透测试的完整框架,利用该工具可以伪造接入点完成中间人攻击,同时也支持一些其他的无线渗透测试功能.旨在提供更安全 ...

  4. Kernel Pwn基础教程之 Double Fetch

    一.前言 Double Fetch是一种条件竞争类型的漏洞,其主要形成的原因是由于用户态与内核态之间的数据在进行交互时存在时间差,我们在先前的学习中有了解到内核在从用户态中获取数据时会使用函数copy ...

  5. 配置文件 /etc/profile出错导致ls,vi不能用

    配置文件 /etc/profile出错导致ls,vi不能用   关于 Linux 的配置文件 /etc/profile 路径出错后相关的命令失效解决方式(如:ls,vi不能用)   一般我记得vi是在 ...

  6. S7-1200学习记录

    型号:CPU 1212C DC/DC/DC 硬件包括CPU模块.信号模块(输入输出).通信模块.屏幕面板 1.通信模块 S7-1200最多可以添加3块通信模块,可以使用点对点通信模块.PROFIBUS ...

  7. 羽夏看Win系统内核—— x64 番外篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  8. 一图学Python

    网上有这样一张图片,信息量很大,通常会被配上标题"一张图让你学会Python": 这张图流传甚广,但我没有找到明确的出处,图片上附带了 UliPad 的作者 Limodou 的信息 ...

  9. python3 爬虫5--分析Robots协议

    1Robots协议 Robots协议告诉了搜索引擎和爬虫那些页面可以抓取,那些不可以,通常是存放在robots.txt文件里面,位于网站的根目录下 robots.txt中内容的示范: User-age ...

  10. Oracle问题解决记录

    一.前言 oracle这么一个庞大的东西,出点问题真是太常见了.开个博客,用于记录遇到的问题吧. 持续更新. 二.问题列表 归档日志满,引起的问题. 一台服务器,用了很久了,某天,出现了磁盘空间占满的 ...