责任链模式计算一个过去时间在xxx年/月/周/天/时/分/秒之前

本文介绍了如何利用责任链模式来实现灵活的时间差显示,例如文章评论、动态发表和代码提交时间等。通过定义接口和一系列处理者,如年、月、周、天等策略,实现了按需计算不同时间单位前的时间表达。这种方式使得代码易于理解和扩展,同时也方便增减不同的时间单位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候,需要计算一个过去时间在xxx年/月/周/天/时/分/秒之前。比如我们经常看到的文章评论时间、动态发表时间、代码提交时间等,如下

怎么实现呢?逻辑是这样的:

1、判断时间差是否超过1年,是的话直接计算xxx年前,否则往下走;

2、判断时间差是否超过1个月,是的话直接计算xxx月前,否则往下走;

3、判断时间差是否超过1个星期,是的话直接计算xxx周前,否则往下走;

4、判断时间差是否超过1天,是的话直接计算xxx天前,否则往下走;

5、判断时间差是否超过1小时,是的话直接计算xxx小时前,否则往下走;

6、判断时间差是否超过1分钟,是的话直接计算xxx分钟前,否则往下走;

7、判断时间差是否超过1秒,是的话直接计算xxx秒前,否则往下走;

8、返回“刚刚”或者其它毫秒等。

有了方案,顿时精神百倍准备撸码,没有if...else解决不了的哈哈哈。。。

不过,好的代码要经得起理解、修改和扩展。哪一天我突然不要星期了,你是不是要找到星期那部分代码注释掉?哪一天我需要增加半天,你是不是要加个if?我一个地方要分钟,一个地方又不需要,你咋办?

这里直接秀出责任链模式(之前写过详细介绍)的实现,就能解决以上问题。

1)统一定义这条链上处理者的责任,即接口(可优化点:定义返回执行顺序的方法)。

public interface IStrategy {

    /**
     * 把期间转换成具体的表示存放到结果里面。并由自己确定是否交给下一个处理者
     *
     * @param duration 两个时间的间隔
     * @param result 结果包装对象
     * @param strategyChain 责任链对象,用于内部控制请求的传递
     */
    void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain);
}

结果包装对象定义如下

public class ObjectWrapper<V> {
    private V value;

    public ObjectWrapper() {}

    public ObjectWrapper(V value) {
        this.value = value;
    }

    public V getValue() {
        return this.value;
    }

    public void setValue(V value) {
        this.value = value;
    }
}

2)定义责任链。由链上的处理者控制请求的传递。

public final class DurationStrategyChain {
    /** 请求到达链上的位置 */
    private int pos = 0;
    /** 链上处理者的数量 */
    private int n;
    /** 链上处理者 */
    private IStrategy[] strategies;
 
    private DurationStrategyChain() {
    }

    /**
     * 构建责任链对象
     *
     * @param strategies 处理者数组
     * @return 责任链对象
     */
    public static DurationStrategyChain build(IStrategy[] strategies) {
        DurationStrategyChain instance = new DurationStrategyChain();
        instance.strategies = Objects.requireNonNull(strategies, "DurationStrategyChain构造参数strategies不能为空!");
        instance.n = strategies.length;
        return instance;
    }

    /**
     * 责任链执行
     *
     * @param duration 两个时间的间隔
     * @param result 结果包装对象
     */
    public void doCompute(Duration duration, ObjectWrapper<String> result) {
        if (pos < n) {
            strategies[pos++].compute(duration, result, this);
        }
    }
}

3)定义责任链的处理者(可优化点:可以把它们定义成单例)。

public class YearStrategy implements IStrategy {

    private static final int DAY_OF_YEAR = 365;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long days = duration.toDays();
        if (days >= DAY_OF_YEAR) {
            long years = days / DAY_OF_YEAR;
            result.setValue(years + "年前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

public class MonthStrategy implements IStrategy {

    private static final int DAY_OF_MONTH = 30;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long days = duration.toDays();
        if (days >= DAY_OF_MONTH) {
            long months = days / DAY_OF_MONTH;
            result.setValue(months + "月前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

public class WeekStrategy implements IStrategy {

    private static final int DAY_OF_WEEK = 7;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long days = duration.toDays();
        if (days >= DAY_OF_WEEK) {
            long weeks = days / DAY_OF_WEEK;
            result.setValue(weeks + "周前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

public class DayStrategy implements IStrategy {

    private static final int HOUR_OF_DAY = 24;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long hours = duration.toHours();
        if (hours >= HOUR_OF_DAY) {
            long days = hours / HOUR_OF_DAY;
            result.setValue(days + "天前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

public class HourStrategy implements IStrategy {

    private static final int MINUTE_OF_HOUR = 60;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long minutes = duration.toMinutes();
        if (minutes >= MINUTE_OF_HOUR) {
            long hours = minutes / MINUTE_OF_HOUR;
            result.setValue(hours + "小时前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

public class MinuteStrategy implements IStrategy {

    private static final int SECOND_OF_MINUTE = 60;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long seconds = duration.getSeconds();
        if (seconds >= SECOND_OF_MINUTE) {
            long minutes = seconds / SECOND_OF_MINUTE;
            result.setValue(minutes + "分钟前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

public class SecondStrategy implements IStrategy {

    private static final int MILLISECOND_OF_SECOND = 1000;

    @Override
    public void compute(Duration duration, ObjectWrapper<String> result, DurationStrategyChain strategyChain) {
        long millis = duration.toMillis();
        if (millis >= MILLISECOND_OF_SECOND) {
            long seconds = millis / MILLISECOND_OF_SECOND;
            result.setValue(seconds + "秒前");
        } else {
            strategyChain.doCompute(duration, result);
        }
    }
}

后面也可以再定义一个默认的,走到这里表示异常或者“刚刚”什么的。

4)测试走起

这里面7个处理者我们全部都用了。你也可以只选一部分,不过要保证顺序。

public class Test {

    private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        IStrategy[] strategies = {new YearStrategy(), new MonthStrategy(), new WeekStrategy(), new DayStrategy(), new HourStrategy(), new MinuteStrategy(), new SecondStrategy()};
        DurationStrategyChain durationStrategyChain = DurationStrategyChain.build(strategies);
        ObjectWrapper<String> result = new ObjectWrapper<>();

        durationStrategyChain.doCompute(getDuration("2018-10-05 00:00:00", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 2年前

        durationStrategyChain.doCompute(getDuration("2020-02-05 00:00:00", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 11月前

        durationStrategyChain.doCompute(getDuration("2020-12-12 00:00:00", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 2周前

        durationStrategyChain.doCompute(getDuration("2020-12-29 05:00:00", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 2天前

        durationStrategyChain.doCompute(getDuration("2020-12-31 12:30:00", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 11小时前

        durationStrategyChain.doCompute(getDuration("2020-12-31 23:15:02", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 44分钟前

        durationStrategyChain.doCompute(getDuration("2020-12-31 23:59:10", "2021-01-01 00:00:00"), result);
        System.out.println(result.getValue());// 50秒前
    }

    private static Duration getDuration(String beforeDateTime, String nowDateTime) {
        return Duration.between(LocalDateTime.parse(beforeDateTime, DTF), LocalDateTime.parse(nowDateTime, DTF));
    }
}

执行结果如下,也把结果注释到测试代码里面了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值