首页 > 编程语言 >一个面试题:计算时间偏移量,怎么设计你的程序?

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

时间:2023-07-19 15:01:15浏览次数:42  
标签:面试题 return 程序 偏移量 偏移 param key offset date

计算时间偏移量,例如,计算当前时间向前偏移 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),香香的,甜甜的!

坦白说,写出来这个util并不难,你可以写出来你的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 ----------------------------------------------

 

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

同样,关于本地缓存工具,分享一段我曾经写的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)重载。--——————这是一个优秀编码风格,标记弃用,请向使用者描述背景(弃用原因)或告知使用者应该怎么办。

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

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

 

The End.

 

标签:面试题,return,程序,偏移量,偏移,param,key,offset,date
From: https://www.cnblogs.com/buguge/p/17565583.html

相关文章

  • mysql字符串类型面试题
    mysql有哪些字符串类型?MySQL中有以下几种常见的字符串类型:CHAR:固定长度字符串,最多可以存储255个字符。VARCHAR:可变长度字符串,最多可以存储65535个字符。TEXT:用于存储较长的文本字符串,最多可以存储65535个字符。TINYTEXT:用于存储非常短的文本字符串,最多可以......
  • huilder 无法调试微信小程序方法
    huilder无法调试微信小程序方法 npxbrowserslist@latest--update-db​14:20:29.948项目'test11'编译成功。前端运行日志,请另行在小程序开发工具的控制台查看。14:20:29.953正在启动微信开发者工具...14:20:30.328[微信小程序开发者工具]-initialize14:20:30.330[微......
  • 直播网站程序源码,Flutter:列表布局摘要
    直播网站程序源码,Flutter:列表布局摘要方式1(推荐,适用大量item,动态创建item): ListView.builder(//列表布局 scrollDirection:Axis.vertical, //(默认)vertical垂直排列,horizontal水平排列 itemCount:总个数,        //item总个数 itemExtent:高度值......
  • 影响 Java 程序的性能的因素和性能指标
    有哪些因素会影响Java程序的性能?执行速度:程序的反应是否迅速,响应时间是否足够短内存分配:内存分配是否合理,是否过多地消耗内存或者存在泄漏启动时间:程序从运行到可以正常处理业务需要花费多少时间负载承受能力:当系统压力上升时,系统的执行速度、响应时间的上升曲线是否平缓......
  • SecureBootEncodeUEFI 是一个操作系统启动过程中的安全功能,用于验证操作系统和驱动程
    SecureBootEncodeUEFI是一个操作系统启动过程中的安全功能,用于验证操作系统和驱动程序的签名,确保它们是由受信任的发行商发布并没有遭到篡改。这种技术可以防止恶意软件在系统启动时运行,并提供额外的安全层。SecureBootEncodeUEFI通常在计算机的UEFI(统一扩展固件接口)固件中实......
  • .net 6 winform启动器:调用CMD命令行执行dotnet命令启动.net core程序并将控制台输出日
    背景历史遗留问题,生产车间运行的一个.netcoresignalr程序使用命令行程序启动,经常由于生产人员误操作将光标停留在控制台上导致程序假死,丢失部分测试数据,车间随便找了一台win10系统部署的程序,源代码遗失,电脑也是阉割版,原开发者已经离职多年无人敢动,于是想了一个歪门邪道发方......
  • SuperFetch 是什么: SuperFetch 是一种内存管理技术,它利用空闲内存缓存经常使用的应用
    SuperFetch是Windows操作系统中的一个功能,旨在提高程序的启动速度和系统响应时间。下面是关于SuperFetch的详细解释:SuperFetch是什么:SuperFetch是一种内存管理技术,它利用空闲内存缓存经常使用的应用程序和文件,以提高它们的访问速度。通过分析用户的使用习惯和模式,SuperFe......
  • 施耐德plc上传程序方法转以太网模块
    捷米特JM-ETH-SC是一款经济型的以太网通讯处理器,是为满足日益增多的工厂设备信息化需求(设备网络监控和生产管理)而设计,用于施耐德Quantumn/Premiun/TSXMicro/Twdio/M200/M218/M221/M241/M238/M25等系列PLC的以太网数据采集,非常方便构建生产管理系统。其中串口既支持RS485,也......
  • Visual Studio 2022 .NET 7读取程序集版本
    如果你也像我一样是从.NetFramwork升级到.Net7版本,那大概率会碰到不能正常读取Assembly下的正确程序集版本号,利用asm.GetName().Version读到的是0.0.0.0,解决方法是新建一个项目,并将“AssemblyInfo.cs”复制到你的项目下Properties内。一些产品名称、公司信息等自行修改,Guid可......
  • uniapp小程序客服拖拽+左右吸附
    <template> <viewclass=""v-if="x!=0&&y!=0"> <movable-areaclass="movableArea"> <movable-viewclass="movableView":position="position":x="x":y="y&q......