当前位置: 首页 > 图灵资讯 > 技术篇> 实战:求年月日时间前后遇到的坑和解决方式

实战:求年月日时间前后遇到的坑和解决方式

来源:图灵教育
时间:2023-06-20 09:37:47

前言

本周,这边收到了一个需要处理的时间转换任务。没有问题。后来,在完成后,发现时间有偏差,并重写了代码。觉得有必要记录下来。希望大家能避开这个坑。像往常一样,先得出结论。

正确实例:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstants.DATE_FORMAT);LocalDateTime now = LocalDateTime.now();

错误实例:

Calendar calendar = Calendar.getInstance();

结果:如果我们使用错误的工具类型,时间和秒会有偏差,玩几个小时,小到十秒。这段时间的偏差是我们无法忍受的。

需求

这项工作要求一个接口将部分参数传输给我们,然后根据参数找出相应的数据,如昨天和今天、三小时、天、月、年后等。以下是代码实例。像往常一样,把它放对,错误地留给你参考。

///找出年月日小时要求的时间publicic Intent dateforParams2(Intent intent, String time) {    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstants.DATE_FORMAT);    LocalDateTime now = LocalDateTime.now();    String endTime = now.format(formatter);    // 将时间向前推移1小时    if (CommonConstants.HeHaiTimeKey.HOUR_1.equals(time)) {        now = now.minusHours(1);    }    if (CommonConstants.HeHaiTimeKey.HOUR_3.equals(time)) {        now = now.minusHours(3);    }    if (CommonConstants.HeHaiTimeKey.HOUR_24.equals(time)) {        now = now.minusDays(1);    }    if (CommonConstants.HeHaiTimeKey.HOUR_48.equals(time)) {        now = now.minusDays(2);    }    if (CommonConstants.HeHaiTimeKey.HOUR_72.equals(time)) {        now = now.minusDays(3);    }    // 将日期向前推移3天    if (CommonConstants.HeHaiTimeKey.DAY_3.equals(time)) {        now = LocalDateTime.of(                now.minusDays(3).toLocalDate(),                LocalTime.of(8, 0, 0)            // 设置为8点整        );    }    if (CommonConstants.HeHaiTimeKey.DAY_7.equals(time)) {        now = LocalDateTime.of(                now.minusDays(7).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    if (CommonConstants.HeHaiTimeKey.DAY_15.equals(time)) {        now = LocalDateTime.of(                now.minusDays(15).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    if (CommonConstants.HeHaiTimeKey.DAY_30.equals(time)) {        now = LocalDateTime.of(                now.minusDays(30).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    // 月份向前推进3个月    if (CommonConstants.HeHaiTimeKey.THREE_MONTH.equals(time)) {        now = LocalDateTime.of(                now.minusMonths(3).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    if (CommonConstants.HeHaiTimeKey.HALF_YEAR.equals(time)) {        // 月份向前推进6个月        now = LocalDateTime.of(                now.minusMonths(6).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    // 向前推进一年的年份    if (CommonConstants.HeHaiTimeKey.ONE_YEAR.equals(time)) {        now = LocalDateTime.of(                now.minusYears(1).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    if (CommonConstants.HeHaiTimeKey.THREE_YEAR.equals(time)) {        now = LocalDateTime.of(                now.minusYears(3).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    if (CommonConstants.HeHaiTimeKey.FIVE_YEAR.equals(time)) {        now = LocalDateTime.of(                now.minusYears(5).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    if (CommonConstants.HeHaiTimeKey.TEN_YEAR.equals(time)) {        now = LocalDateTime.of(                now.minusYears(10).toLocalDate(),                LocalTime.of(8, 0, 0)        );    }    //早上8点设置    if (CommonConstants.HeHaiTimeKey.TODAY.equals(time)) {        now = LocalDateTime.of(                now.toLocalDate(),          // 使用当前日期                LocalTime.of(8, 0, 0)      // 设置为8点整        );    }    if (CommonConstants.HeHaiTimeKey.YESTERDAY.equals(time)) {        //减去1天        now = LocalDateTime.of(                now.minusDays(1).toLocalDate(),                LocalTime.of(8, 0, 0)        );        // 结束日期是今天8点。        endTime = eightforNow2(0);    }    if (CommonConstants.HeHaiTimeKey.LAST_DAY.equals(time)) {        //减去2天        now = LocalDateTime.of(                now.minusDays(2).toLocalDate(),                LocalTime.of(8, 0, 0)        );        // 结束日期是昨天8点        endTime = eightforNow2(1);    }    String startTime = now.format(formatter);    log.info(输出开始时间:{} startTime);    intent.setStartTime(startTime);    intent.setEndTime(endTime);    return intent;}

 

 

/** * 求出早8点 */public String eightforNow2(Integer day) {    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstants.DATE_FORMAT);    LocalDateTime now = LocalDateTime.now();    if (day != null) {        if (day == 0) {            now = LocalDateTime.of(                    now.toLocalDate(),          // 使用当前日期                    LocalTime.of(8, 0, 0)      // 设置为8点整            );        } else {            now = LocalDateTime.of(                    now.minusDays(day).toLocalDate(),                    LocalTime.of(8, 0, 0)            );        }    }    return now.format(formatter);}

由于需求开发时间小,需求时间短,使用频率低,没有集成工具类。有些常用的工具可以集成到你的时间工具类中。

-------------------------------错误-------------------------------

/** * 根据Params找到不同的时间 */public Intent dateForParams(Intent intent, String time) {    SimpleDateFormat format = new SimpleDateFormat(CommonConstants.DATE_FORMAT);    Calendar calendar = Calendar.getInstance(); //获取日历实例    String endTime = format.format(calendar.getTime());//以后结束时间    calendar.setTime(date); ///将当前时间设置为日历实例    int hour = calendar.get(Calendar.HOUR_OF_DAY); // 获取当前的小时数    // 将时间向前推移1小时    if (CommonConstants.HeHaiTimeKey.HOUR_1.equals(time)) {        if (hour < 1) {            calendar.add(Calendar.DAY_OF_MONTH, -1); // 将日期向前推移一天            hour += 24; // 计算相应的小时数            calendar.add(Calendar.HOUR_OF_DAY, hour - 1);        } else {            calendar.add(Calendar.HOUR_OF_DAY, -1);        }    }    if (CommonConstants.HeHaiTimeKey.HOUR_3.equals(time)) {        if (hour < 1) {            calendar.add(Calendar.DAY_OF_MONTH, -1); // 将日期向前推移一天            hour += 24; // 计算相应的小时数            calendar.add(Calendar.HOUR_OF_DAY, hour - 3);        } else {            calendar.add(Calendar.HOUR_OF_DAY, -3);        }    }    if (CommonConstants.HeHaiTimeKey.HOUR_24.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -1);    }    if (CommonConstants.HeHaiTimeKey.HOUR_48.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -2);    }    if (CommonConstants.HeHaiTimeKey.HOUR_72.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -3);    }    // 将日期向前推移3天    if (CommonConstants.HeHaiTimeKey.DAY_3.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -3);        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);    }    if (CommonConstants.HeHaiTimeKey.DAY_7.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -7);        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);    }    if (CommonConstants.HeHaiTimeKey.DAY_15.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -15);        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);    }    if (CommonConstants.HeHaiTimeKey.DAY_30.equals(time)) {        calendar.add(Calendar.DAY_OF_MONTH, -30);        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);    }    // 月份向前推进3个月    if (CommonConstants.HeHaiTimeKey.THREE_MONTH.equals(time)) {        calendar.add(Calendar.MONTH, -3);    }    if (CommonConstants.HeHaiTimeKey.HALF_YEAR.equals(time)) {        // 月份向前推进6个月        calendar.add(Calendar.MONTH, -6);    }    // 向前推进一年的年份    if (CommonConstants.HeHaiTimeKey.ONE_YEAR.equals(time)) {        calendar.add(Calendar.YEAR, -1);    }    if (CommonConstants.HeHaiTimeKey.THREE_YEAR.equals(time)) {        calendar.add(Calendar.YEAR, -3);    }    if (CommonConstants.HeHaiTimeKey.FIVE_YEAR.equals(time)) {        calendar.add(Calendar.YEAR, -5);    }    if (CommonConstants.HeHaiTimeKey.TEN_YEAR.equals(time)) {        calendar.add(Calendar.YEAR, -10);    }    //早上8点设置    if (CommonConstants.HeHaiTimeKey.TODAY.equals(time)) {        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);    }    if (CommonConstants.HeHaiTimeKey.YESTERDAY.equals(time)) {        //减去1天        calendar.add(Calendar.DAY_OF_MONTH, -1);        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);        // 结束日期是今天8点。        endTime = eightForNow(null);        intent.setEndTime(endTime);    }    if (CommonConstants.HeHaiTimeKey.LAST_DAY.equals(time)) {        //减去2天        calendar.add(Calendar.DAY_OF_MONTH, -2);        calendar.set(Calendar.HOUR_OF_DAY, 8);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);        // 结束日期是昨天8点        endTime = eightForNow(1);        intent.setEndTime(endTime);    }    String startTime;    Date dayTime = calendar.getTime();    if (CommonConstants.HeHaiTimeKey.REAL_TIME.equals(time)) {        startTime = endTime;    } else {        startTime = format.format(dayTime); ///将时间格式化为字符串    }    log.info(输出开始时间:{} startTime);    intent.setStartTime(startTime);    intent.setEndTime(endTime);    return intent;}/** * 求出早8点 */public String eightForNow(Integer day) {    Calendar calendar = Calendar.getInstance(); //获取日历实例    calendar.setTime(date); ///将当前时间设置为日历实例    if (day != null) {        calendar.add(Calendar.DAY_OF_MONTH, -day); //减去相应的天数    }    calendar.set(Calendar.HOUR_OF_DAY, 8); //早上8点设置    calendar.set(Calendar.MINUTE, 0);    calendar.set(Calendar.SECOND, 0);    Date esterday8yyyesterdayam = calendar.getTime(); ///昨天早上8点得到时间    SimpleDateFormat format = new SimpleDateFormat(CommonConstants.DATE_FORMAT);    String formattedDateTime = format.format(esterday8yyyesterdayam);    log.info(输出开始时间:{} formattedDateTime);    return formattedDateTime;}

 

Calendar是Java中的处理日期和时间类别,它提供了各种实用的操作日历、时间和时间的方法。过去,Java的日期和时间类别主要使用Date和Simpledateformat,但这两类存在线程不安全、可变性等问题,因此Java Calendar类在1.1中被引入替代。

 

calendar类是一种抽象类,不能直接创建对象,可以通过getinstance()获得其实例。日期和时间信息通过set()设置,getTime()方法获得Date类型的时间,get()获取年月日等信息的方法。

calendar类提供了加减时间的方法,add()加减某个时间单位的方法,例如,可以使用addd(Calendar.DATE, 1)增加一天,也可以使用add(Calendar.MONTH, -1)减少一个月。roll()方法是这样做的一种变体,它只修改指定的字段,而不是更改较高的字段。

calendar类别还提供了许多有用的方法来操纵和显示日期和时间,比如获得当前星期的开始日,getMinimum()获得给定日历字段的最小值等。

尽管Calendar类有很多优点,但它仍然没有解决Date类的基本问题。在Java 在8中,Localdatetime类被引入,作为更简单、更灵活的实现,以取代calendar和date。本地日期时间类为Java程序员提供了一种更自然地处理日期和时间的方法,避免了时间区域的混淆和线程安全问题。

LocalDatetimeJava 8新增加的日期时间类代表了一个没有时间区域的日期和时间,用于处理当地日期和时间。它的例子可以存储到精确到纳秒的时间。

Localdatetime的初始化可以通过now()调用获得当前的日期和时间,也可以通过of()创建指定的日期和时间。其中,now()方法的具体实现是通过系统时钟获得当前时间,of()方法接受年、月、日、时、分、秒、纳秒的七个参数。

Localdatetime还提供了许多操纵日期和时间的方法,如增加或减少日期时间、计算日期间隔、格式化日期时间等。这可以很容易地进行日常开发。对于需要考虑时区的应用程序,Java 8还提供Zoneddatetime类别。

Localdatetime是一种非常实用的日期和时间处理类,可以满足大多数应用程序对日期和时间的需求。

以上都是官网给出的一些答案,所以我们也可以看到,使用localdatetime是更好的选择,还在使用caldatetetime的人可以尝试更换,不要停留在旧时代。

代码不难具体解释,注释也很多。如果你什么都不知道,你可以评论下面的提议。当你看到它时,你会很快回复。

ps:有些朋友可能真的刚接触过。这里有一个calender的例子,试着把它修改成localdatetime。你不能前者,后者不能。

public static void main(String[] args) throws ParseException {    String dateTimeString = "2023-06-13 02:00:00";    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    Date date1 = format.parse(dateTimeString); // 解析为 Date 对象    Calendar calendar = Calendar.getInstance(); //获取日历实例    calendar.setTime(date1); //将当前时间设置为日历实例//这里零时转换可以忽略不计,LocalDatetime在这方面没有麻烦    int hour = calendar.get(Calendar.HOUR_OF_DAY); // 获取当前的小时数    if (hour < 1) { // 若小时数小于1,需要特殊处理        calendar.add(Calendar.DAY_OF_MONTH, -1); // 将日期向前推移一天        hour += 24; // 计算相应的小时数    }    //calendar.set(Calendar.HOUR_OF_DAY, hour - 72); // 将时间向前推移1小时    calendar.add(Calendar.YEAR, -10); // 年份向前推进了10年    Date esterday8yyyesterdayam = calendar.getTime();    String formattedDateTime = format.format(esterday8yyyesterdayam); ///将时间格式化为字符串    System.out.println(“输出结果:”+formattedDateTime); //输出结果}