java线程安全的时间格式化

使用ThreadLocal和SimpleDateFormat

    private static final ThreadLocal sdf = ThreadLocal.withInitial(
            () -> new SimpleDateFormat("yyyy-MM-dd")
    );

这种办法使用简单,但是不灵活,如果有多种格式化的要求,则需要建很多对象,而且当线程没有合理控制,不断死亡和增加,大量的threadLocal会增加gc负担

如果不想使用第三方库比如joda,基于java9实现:

public class DateFormatUtilsTest {
    @org.junit.Test
    public void format() throws Exception {
        System.out.println(DateFormatUtils.format(new Date(),"yyyy-MM-dd"));
        System.out.println(DateFormatUtils.format(new Date(),"HH:mm:ss"));
        System.out.println(DateFormatUtils.format(new Date(),"MM月月dd日日ss秒秒"));
    }

    @org.junit.Test
    public void parse() throws Exception {
        System.out.println(DateFormatUtils.parse("16:20","HH:mm"));
        System.out.println(DateFormatUtils.parse("2016年12月","yyyy年MM月"));
        System.out.println(DateFormatUtils.parse("10-20","MM-dd"));
        System.out.println(DateFormatUtils.parse("2014-09-06 11:53:50","yyyy-MM-dd HH:mm:ss"));
    }

}
package com.fly.design.utils;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * @author weijun.zou
 * Create on 2018/3/7
 */
public class DateFormatUtils {

    private static Map>> parseMapper = Map.of(
            2, Map.of(
                    'M', (calendar, string) -> calendar.set(Calendar.MONTH, Integer.valueOf(string) - 1),
                    'd', (calendar, string) -> calendar.set(Calendar.DAY_OF_MONTH, Integer.valueOf(string)),
                    'H', (calendar, string) -> calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(string)),
                    'h', (calendar, string) -> calendar.set(Calendar.HOUR, Integer.valueOf(string)),
                    'm', (calendar, string) -> calendar.set(Calendar.MINUTE, Integer.valueOf(string)),
                    's', (calendar, string) -> calendar.set(Calendar.SECOND, Integer.valueOf(string))
            ),
            4, Map.of(
                    'y', (calendar, string) -> calendar.set(Calendar.YEAR, Integer.valueOf(string))
            )
    );

    private static Map>> formatMapper = Map.of(
            2, Map.of(
                    'M', calendar -> String.format("%02d", calendar.get(Calendar.MONTH) + 1),
                    'd', calendar -> String.format("%02d", calendar.get(Calendar.DAY_OF_MONTH)),
                    'H', calendar -> String.format("%02d", calendar.get(Calendar.HOUR_OF_DAY)),
                    'h', calendar -> String.format("%02d", calendar.get(Calendar.HOUR)),
                    'm', calendar -> String.format("%02d", calendar.get(Calendar.MINUTE)),
                    's', calendar -> String.format("%02d", calendar.get(Calendar.SECOND))
            ),
            4, Map.of(
                    'y', calendar -> String.format("%04d", calendar.get(Calendar.YEAR))
            )
    );

    /**
     * 将时间按照格式转字符串
     * format格式
     * yyyy: 年
     * MM: 月
     * dd: 日
     * HH: 时
     * mm: 分
     * ss: 秒
     */
    public static String format(Date date, String format) {
        Objects.requireNonNull(date);
        Objects.requireNonNull(format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        char[] chars = format.toCharArray();
        for (int i = 0; i < chars.length; ) {
            int overlap = overlap(chars, i);
            if (formatMapper.getOrDefault(overlap, Map.of()).containsKey(chars[i])) {
                String value = formatMapper.get(overlap).get(chars[i]).apply(calendar);
                replace(chars, value.toCharArray(), i);
            }
            i += overlap;
        }
        return new String(chars);
    }

    public static Date parse(String dateString, String format) {
        return modify(new Date(), dateString, format);
    }

    public static Date modify(Date date, String dateString, String format) {
        Objects.requireNonNull(date);
        Objects.requireNonNull(dateString);
        Objects.requireNonNull(format);
        if (dateString.length() != format.length()) {
            throw new IllegalArgumentException(dateString);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        char[] chars = format.toCharArray();
        for (int index = 0; index < chars.length; ) {
            int overlap = overlap(chars, index);
            if (parseMapper.containsKey(overlap) && parseMapper.get(overlap).containsKey(chars[index])) {
                parseMapper.get(overlap).get(chars[index])
                        .accept(calendar, dateString.substring(index, index + overlap));
            }
            index += overlap;
        }
        return calendar.getTime();
    }

    private static int overlap(char[] chars, int index) {
        char c = chars[index];
        int number = 0;
        while (index < chars.length && chars[index++] == c) {
            number++;
        }
        return number;
    }

    private static void replace(char[] target, char[] copy, int index) {
        for (int i = 0; index < target.length && i < copy.length; index++, i++) {
            target[index] = copy[i];
        }
    }
}

你可能感兴趣的:(算法)