一个面试题:计算时间偏移量,怎么设计你的程序?

这篇具有很好参考价值的文章主要介绍了一个面试题:计算时间偏移量,怎么设计你的程序?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一个面试题:计算时间偏移量,怎么设计你的程序?

计算时间偏移量,例如,计算当前时间向前偏移 30 秒的时间,我们利用java.util.Calendar很容易实现。

    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date());
    cal.add(Calendar.SECOND, -30);
    System.out.println(cal.getTime());

 

我在组织公司的技术招聘面试的时候,关于程序设计,有问过应聘者这样的问题。

那么,我们怎么封装这么一个工具类呢?这个工具类提供哪些工具方法呢?每个方法又当怎么实现呢?

下面这段优秀的代码节选自hutool-DateUtil(hutool-all-4.5.18.jar ,maven坐标:cn.hutool:hutool-all:4.5.18),香香的,甜甜的,pretty,graceful,pretty graceful.

坦白说,写出来这个util并不难,你可以写出来你的代码,然后做个比较,看看与优秀代码的差距。

    // --------------------------------------------------- Offset for now
    /**
     * 昨天
     * 
     * @return 昨天
     */
    public static DateTime yesterday() {
        return offsetDay(new DateTime(), -1);
    }

    /**
     * 明天
     * 
     * @return 明天
     * @since 3.0.1
     */
    public static DateTime tomorrow() {
        return offsetDay(new DateTime(), 1);
    }

    /**
     * 上周
     * 
     * @return 上周
     */
    public static DateTime lastWeek() {
        return offsetWeek(new DateTime(), -1);
    }

    /**
     * 下周
     * 
     * @return 下周
     * @since 3.0.1
     */
    public static DateTime nextWeek() {
        return offsetWeek(new DateTime(), 1);
    }

    /**
     * 上个月
     * 
     * @return 上个月
     */
    public static DateTime lastMonth() {
        return offsetMonth(new DateTime(), -1);
    }

    /**
     * 下个月
     * 
     * @return 下个月
     * @since 3.0.1
     */
    public static DateTime nextMonth() {
        return offsetMonth(new DateTime(), 1);
    }

    /**
     * 偏移毫秒数
     * 
     * @param date 日期
     * @param offset 偏移毫秒数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetMillisecond(Date date, int offset) {
        return offset(date, DateField.MILLISECOND, offset);
    }

    /**
     * 偏移秒数
     * 
     * @param date 日期
     * @param offset 偏移秒数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetSecond(Date date, int offset) {
        return offset(date, DateField.SECOND, offset);
    }

    /**
     * 偏移分钟
     * 
     * @param date 日期
     * @param offset 偏移分钟数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetMinute(Date date, int offset) {
        return offset(date, DateField.MINUTE, offset);
    }

    /**
     * 偏移小时
     * 
     * @param date 日期
     * @param offset 偏移小时数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetHour(Date date, int offset) {
        return offset(date, DateField.HOUR_OF_DAY, offset);
    }

    /**
     * 偏移天
     * 
     * @param date 日期
     * @param offset 偏移天数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetDay(Date date, int offset) {
        return offset(date, DateField.DAY_OF_YEAR, offset);
    }

    /**
     * 偏移周
     * 
     * @param date 日期
     * @param offset 偏移周数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetWeek(Date date, int offset) {
        return offset(date, DateField.WEEK_OF_YEAR, offset);
    }

    /**
     * 偏移月
     * 
     * @param date 日期
     * @param offset 偏移月数,正数向未来偏移,负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetMonth(Date date, int offset) {
        return offset(date, DateField.MONTH, offset);
    }

    /**
     * 获取指定日期偏移指定时间后的时间
     * 
     * @param date 基准日期
     * @param dateField 偏移的粒度大小(小时、天、月等){@link DateField}
     * @param offset 偏移量,正数为向后偏移,负数为向前偏移
     * @return 偏移后的日期
     */
    public static DateTime offset(Date date, DateField dateField, int offset) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(dateField.getValue(), offset);
        return new DateTime(cal.getTime());
    }

    // ------------------------------------ Offset end ----------------------------------------------

 

一个面试题:计算时间偏移量,怎么设计你的程序?

为什么说这么代码比较香呢?你品,你细品!

  • 易读。注意各个方法尤其是以“offset”开头的方法的签名,包括方法名、方法参数,包括javadoc,相当清晰,易读易理解。另外,这几个方法整体来看,像极了我们母语中的排比句。
  • 丰富。按不同的时间单位(如秒、分钟、小时、天、周和月)偏移日期时间值,定义了丰富的方法,各种姿势满足你。
  • 易用。除了offsetMinute/offsetSecond等offsetXxx方法,还提供了yesterday / tomorrow / lastWeek / nextWeek / lastMonth /nextMonth等拿来即用的方法,不必再调用offsetXxx。
  • 简洁。计算时间偏移量的算法是相同的,所以,这些方法内部均调用一个通用的 offset 方法,该方法使用 DateField 枚举值指定要偏移的时间单位和偏移量。
  • 包容。注意最后那个public的offset(Date date, DateField dateField, int offset)方法,当上面的计算时间偏移量的方法无法满足使用要求时(当然,已经是应有尽有了),你就可以用它了。

 

同样,关于本地缓存工具,分享一段我曾经编写的基于hutool-cache封装的LocalCacheUtil工具类。

一个面试题:计算时间偏移量,怎么设计你的程序?一个面试题:计算时间偏移量,怎么设计你的程序?
import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * 本地缓存工具
 */
@Slf4j
public class LocalCacheUtil {
    private static Cache<String, Object> lfuCache = CacheUtil.newLFUCache(256, TimeUnit.MINUTES.toMillis(30));
    private static Cache<String, Object> timedCache = CacheUtil.newTimedCache(TimeUnit.DAYS.toMillis(1));//过期时间给个默认值

    /**
     * 从本地缓存获取数据。如果没有,则设置。(策略:最少使用原则)
     *
     * @param key
     * @param supplier
     * @param <T>
     * @return
     *
     * @see #lfuCache
     */
    public static <T> T getCache(String key, Supplier<T> supplier) {
        return getCache(key, false, supplier);
    }

    /**
     * 从本地缓存获取数据。如果没有,则设置。(策略:最少使用原则)
     *
     * @param key
     * @param cacheNullOrEmpty 是否缓存null或空集合
     * @param supplier
     * @param <T>
     * @return
     *
     * @see #lfuCache
     */
    public static <T> T getCache(String key, boolean cacheNullOrEmpty, Supplier<T> supplier) {
        return getCache(lfuCache, key, null, cacheNullOrEmpty, supplier);
    }

    /**
     * 获取缓存。如果没有,则设置
     *
     * @param key
     * @param seconds
     * @param supplier 缓存数据提供者
     * @param <T>
     * @return
     */
    public static <T> T getCache(String key, long seconds, Supplier<T> supplier) {
        return getCache(key, seconds, false, supplier);
    }

    /**
     * 删除缓存
     *
     * @param key 缓存key
     */
    public static void removeCache(String key) {
        timedCache.remove(key);
    }

    /**
     * 获取缓存。如果没有,则设置
     *
     * @param key
     * @param seconds
     * @param cacheNullOrEmpty 是否缓存null或空集合
     * @param supplier         缓存数据提供者
     * @param <T>
     * @return
     */
    public static <T> T getCache(String key, long seconds, boolean cacheNullOrEmpty, Supplier<T> supplier) {
        return getCache(timedCache, key, seconds, cacheNullOrEmpty, supplier);
    }

    private static <T> T getCache(Cache<String, Object> myCache, String key, Long seconds, boolean cacheNullOrEmpty, Supplier<T> supplier) {
        if (myCache.containsKey(key)) {
            return (T) myCache.get(key);
        } else {
            T result = supplier.get();
            if (!cacheNullOrEmpty) {
                if (result == null) {
                    log.info("设置缓存---value为null,不设置--- key={}", key);
                    return null;
                } else if (result instanceof Collection && ((Collection) result).size() == 0) {
                    log.info("设置缓存---value是个空集合,不设置--- key={}", key);
                    return null;
                }
            }
            log.info("设置缓存 key={}", key);
            if (seconds == null) {
                myCache.put(key, result);
            } else {
                myCache.put(key, result, TimeUnit.SECONDS.toMillis(seconds));
            }
            return result;
        }
    }

}
View Code

 

一个面试题:计算时间偏移量,怎么设计你的程序?

另外,在这个DateUtil工具类中,有一个弃用的offsetDate方法如下。

    /**
     * 获取指定日期偏移指定时间后的时间
     * 
     * @param date 基准日期
     * @param dateField 偏移的粒度大小(小时、天、月等){@link DateField}
     * @param offset 偏移量,正数为向后偏移,负数为向前偏移
     * @return 偏移后的日期
     * @deprecated please use {@link DateUtil#offset(Date, DateField, int)}
     */
    @Deprecated
    public static DateTime offsetDate(Date date, DateField dateField, int offset) {
        return offset(date, dateField, offset);
    }

作为一个不断迭代升级的Java工具库,显然hutool不能轻易将之前的方法直接去掉,这会遭到骂娘的。因此,hutool的开发者标记了@Deprecated,并在方法的javadoc里明确指引出来,调用另一个offset(Date, DateField, int)重载。--——————这是一个优秀编码风格,标记弃用,请向使用者描述背景(弃用原因)并告知使用者应该怎么办。(正如阿里巴巴Java开发手册中的【强制】规范:接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。)

一个面试题:计算时间偏移量,怎么设计你的程序?

那么,现在,我们来思考一下:为什么弃用这个offsetDate方法改用offset方法呢?欢迎评论区交流!

我在公司内部的软件系统中,一直在践行关于弃用方法的这一优秀编码行为。只是后来,随着开发经验和意识的增强,在实践过程中做了一些调整。即,我不再一味地标记弃用,而是斩草除根,对于不合理的方法,优秀采用的方式是直接干掉方法并修改对方法的调用,这么做的出发点有三:①我们是中小型内部企业应用系统,工具或组件都是对内使用,具备内部修改的条件;②团队成员编码意识良莠不齐,被明确标记了弃用的方法,有时仍被使用;③最好的方式是一次做好,避免时间一长自己都忘了这些冗余代码了。

 

The End.

 

【EOF】欢迎大家关注微信公众号「靠谱的程序员」,让我们一起做靠谱的程序员。文章来源地址https://www.toymoban.com/news/detail-582142.html

一个面试题:计算时间偏移量,怎么设计你的程序?

到了这里,关于一个面试题:计算时间偏移量,怎么设计你的程序?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包