日常编程中和日期相关的代码和bug

news2025/7/21 1:57:22

本文主要是Java中和日期时间相隔的几个常用代码函数代码,做了总结,希望在日常编码中,可以帮到大家。

1.计算闰年

记住一个短语,“四年一润,百年不闰,四百再润”,不管换啥语言,相信大家不会写错这块的实现代码。
怎么理解呢?转换为我们程序语言就是“

  • 是4的倍数并且不是100的倍数,那么是普通闰年
  • 是400的倍数,那么是世纪闰年

    /**
     * 是否是闰年
     * @param y
     * @return
     */
    public static boolean isLeapYear(int y) {
        if (y % 4 == 0 && y % 100 != 0 || y % 200 == 0) {
            return true;
        } else {
            return false;
        }
    }

2.SimpleDateFormat线程不安全问题

SimpleDateFormat是Java 时间处理上,经常使用到的一个函数,经常用于C-S直接,时间戳处理为当前的格式化的时间。但是大家需要知道,SimpleDateFormat、Date等函数,仅仅是系统的一个功能函数而已,并没有线程同步的功能,所以不可以在多线程环境下,共用一个SimpleDateFormat,不然就会出现相同的时间戳,解析出来的时间不一样的问题。
我们可以看一下SimpleDateFormat的format源码,的确是没有加同步相关的处理逻辑的。

   public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
                                        FieldPosition fieldPosition);

    /**
     * Formats a Date into a date/time string.
     * @param date the time value to be formatted into a time string.
     * @return the formatted time string.
     */
    public final String format(Date date)
    {
        return format(date, new StringBuffer(),
                      DontCareFieldPosition.INSTANCE).toString();
    }

3.定时器的调用

3.1 CountDownTimer

Java中经常会使用到定时器,经常使用的无疑是CountDownTimer

 CountDownTimer countDownTimer = new CountDownTimer(6000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                //每隔1s回调
            }

            @Override
            public void onFinish() {
                //6s倒计时完成回调
            }
        };

当然了,如果在android中的,可选择的API框架更多了,例如:Handler、Rxjava等等
Handler延迟执行

 new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                // 6s后执行的代码
            }
        }, 6000);

但是这里需要注意,大家如果在android中使用CountDownTimer实现倒计时相关需求时,会存在跳秒的问题。
究其原因,是因为handler postDealy会有消息处理第一次的跳变问题(如果使用handler.postDealyed(……, 1000)方式来进行每秒的计时,是不准确的,是的,有很大误差,误差的原因在于在你收到消息,到你重新发出handler.postDealyed的时间,并不是瞬间完成的,这里面有很多逻辑处理的时间,即使没有逻辑处理的时间,handler本身也是耗损性能的,所以消息并不可能按照理想的1000延迟来进行发送,这就导致了误差的累积,怎么解决?

  • 一方面可以通过自己封装CountDownTimer来规避这个错误
  • 一方面可以借助其他第三方框架来实现,例如Rxjava
package com.itbird.design.builder.dialog;

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;

/**
 * 使用android.os.CountDownTimer的源码
 * 添加了onPause、onRestart自定义方法
 * Created by xfkang on 16/3/18.
 */

public abstract class CustomCountDownTimer {
    private static final int MSG = 1;
    /**
     * 总倒计时时间
     * Millis since epoch when alarm should stop.
     */
    private final long mMillisInFuture;
    /**
     * 倒计时间隔时间
     * The interval in millis that the user receives callbacks
     */
    private final long mCountdownInterval;
    /**
     * 记录开始之后,应该停止的时间节点
     */
    private long mStopTimeInFuture;
    /**
     * 记录暂停的时间节点
     */
    private long mPauseTimeInFuture;
    /**
     * 对应于源码中的cancle,即计时停止时
     * boolean representing if the timer was cancelled
     */
    private boolean isStop = false;
    private boolean isPause = false;

    /**
     * @param millisInFuture    总倒计时时间
     * @param countDownInterval 倒计时间隔时间
     */
    public CustomCountDownTimer(long millisInFuture, long countDownInterval) {
        // 解决秒数有时会一开始就减去了2秒问题(如10秒总数的,刚开始就8999,然后没有不会显示9秒,直接到8秒)
        if (countDownInterval > 1000) {
            millisInFuture += 15;
        }
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

    private synchronized CustomCountDownTimer start(long millisInFuture) {
        isStop = false;
        if (millisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + millisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }

    /**
     * 开始倒计时
     */
    public synchronized final void start() {
        start(mMillisInFuture);
    }

    /**
     * 停止倒计时
     */
    public synchronized final void stop() {
        isStop = true;
        mHandler.removeMessages(MSG);
    }

    /**
     * 暂时倒计时
     * 调用{@link #restart()}方法重新开始
     */
    public synchronized final void pause() {
        if (isStop) return;

        isPause = true;
        mPauseTimeInFuture = mStopTimeInFuture - SystemClock.elapsedRealtime();
        mHandler.removeMessages(MSG);
    }

    /**
     * 重新开始
     */
    public synchronized final void restart() {
        if (isStop || !isPause) return;

        isPause = false;
        start(mPauseTimeInFuture);
    }

    /**
     * 倒计时间隔回调
     *
     * @param millisUntilFinished 剩余毫秒数
     */
    public abstract void onTick(long millisUntilFinished);

    /**
     * 倒计时结束回调
     */
    public abstract void onFinish();


    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CustomCountDownTimer.this) {
                if (isStop || isPause) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
                if (millisLeft <= 0) {
                    onFinish();
                } else if (millisLeft < mCountdownInterval) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
}


3.2 Rxjava.interval

Rxjava.interval

  //每隔10s,触发一下accept
Observable.interval(10, TimeUnit.SECONDS)
        .subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                Log.d(TAG + "interval", String.valueOf(aLong));//从0开始输出
            }
        });

这个相当于定时器,用它可以取代CountDownTimer。它会按照设定的间隔时间,每次发送一个事件,发送的事件序列:默认从0开始,无限递增的整数序列 。
那么Rxjava.interval的实现原理是什么呢?这块源码其实,我们之前RxJava系列文章讲解过,这里不再赘述,有兴趣的小伙伴,可以移步查阅。
简言之,就是使用了线程池的ScheduledExecutorService ,定时周期执行任务。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/368635.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HyperGBM用Adversarial Validation解决数据漂移问题

本文作者&#xff1a;杨健&#xff0c;九章云极 DataCanvas 主任架构师 数据漂移问题近年在机器学习领域来越来越得到关注&#xff0c;成为机器学习模型在实际投产中面对的一个主要挑战。当数据的分布随着时间推移逐渐发生变化&#xff0c;需要预测的数据和用于训练的数据分布…

剑指 Offer 30. 包含min函数的栈

摘要 剑指 Offer 30. 包含min函数的栈 一、栈解析 package Stock;import java.util.Stack;/*** Classname JZ30min函数栈* Description TODO* Date 2023/2/24 18:59* Created by xjl*/ public class JZ30min函数栈 {/*** description 最小栈的含义是每次从栈中获取的数据都是…

AWS攻略——使用中转网关(Transit Gateway)连接不同区域(Region)VPC

文章目录Peering方案Transit Gateway方案环境准备创建Transit Gateway Peering Connection接受邀请修改中转网关路由修改被邀请方中转网关路由修改邀请方中转网关路由测试修改Public子网路由知识点参考资料区别于 《AWS攻略——使用中转网关(Transit Gateway)连接同区域(Region…

深入理解Spring Boot的自动配置

通过spring boot可以很方便的独立运行spring应用程序&#xff0c;因为spring boot内嵌了Tomcat、Jetty等servlet容器&#xff0c;切提供自动配置功能&#xff0c;无需进行XML配置即可自动运行应用程序。那么Spring boot启动过程中具体进行了哪些操作呢&#xff1f;下面是Spring…

Julia 数学函数

Julia 提供了一套高效、可移植的标准数学函数。 数值比较 下表列出了用于数值比较的函数&#xff1a; 函数测试是否满足如下性质isequal(x, y)x 与 y 值与类型是否完全相同isfinite(x)x 是否是有限大的数字isinf(x)x 是否是&#xff08;正/负&#xff09;无穷大isnan(x)x 是否…

项目重构,从零开始搭建一套新的后台管理系统

背景 应公司发展需求&#xff0c;我决定重构公司的后台管理系统&#xff0c;从提出需求建议到现在的实施&#xff0c;期间花了将近半个月的时间&#xff0c;决定把这些都记录下来。 之前的后台管理系统实在是为了实现功能而实现的&#xff0c;没有考虑到后期的扩展性&#xf…

SpringMVC常见面试题(2023最新)

目录前言1.简单介绍下你对springMVC的理解?2.说一说SpringMVC的重要组件及其作用3.SpringMVC的工作原理或流程4.SpringMVC的优点5.SpringMVC常用注解6.SpringMVC和struts2的区别7.怎么实现SpringMVC拦截器8.SpringMvc的控制器是不是单例模式&#xff1f;如果是&#xff0c;有什…

关基系统三月重保安全监测怎么做?ScanV提供纯干货!

三月重保当前&#xff0c;以政府、大型国企央企、能源、金融等重要行业和领域为代表的关键信息基础设施运营单位都将迎来“网络安全大考”。 对重要关基系统进行安全风险监测并收敛暴露面&#xff0c;响应监管要求进行安全加固&#xff0c;重保期间实时安全监测与数据汇报等具体…

js函数声明方式*2,对象声明方式*7,不同的调用

目录 一、两种函数声明方式 二、七种对象声明方式 一、两种函数声明方式 【1】命名函数 形如&#xff1a; function fu1(){ let firstName 111111111 let lastName 2222222 console.log(firstName ,lastName ) } function fu2(firstName&#xff0c;lastName ){ …

Linux 线程优先级

目录标题概述Linux进程调度的三种策略Linux 线程优先级对于实时任务对于普通任务top中的PR和NI其他说明代码示例设置为实时进程优先级测试代码概述 概述内容 常见的运用场景&#xff1a; 1&#xff1a;2;3; Linux进程调度的三种策略 SCHED_OTHER&#xff0c;分时调度策略&#…

【读论文】AttentionFGAN

【读论文】AttentionFGAN介绍网络架构提取红外图像目标信息的网络辨别器损失函数生成器损失函数辨别器损失函数总结参考论文&#xff1a; https://ieeexplore.ieee.org/document/9103116/如有侵权请联系博主介绍 好久没有读过使用GAN来实现图像融合的论文了&#xff0c;正好看…

【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day14

大家好&#xff0c;我是陶然同学&#xff0c;软件工程大三今年实习。认识我的朋友们知道&#xff0c;我是科班出身&#xff0c;学的还行&#xff0c;但是对面试掌握不够&#xff0c;所以我将用这100多天更新Java面试题&#x1f643;&#x1f643;。 不敢苟同&#xff0c;相信大…

计算机专业要考什么证书?

大家好&#xff0c;我是良许。 从去年 12 月开始&#xff0c;我已经在视频号、抖音等主流视频平台上连续更新视频到现在&#xff0c;并得到了不错的评价。 视频 100% 原创录制&#xff0c;绝非垃圾搬运号&#xff0c;每个视频都花了很多时间精力用心制作&#xff0c;欢迎大家…

Android高仿陌陌应用点点滑动效果

效果图&#xff1a;分析:从效果上看图片的展示具有层次感&#xff0c;在数据结构上更像是stack,所以通过继承FrameLayout来实现&#xff08;不清楚FrameLayout布局特点的可以先百度下哈&#xff09;&#xff0c;外面是通过继承FrameLayout自定义的TinderStackLayout&#xff0c…

SpringBoot-基础篇

SpringBoot基础篇 ​ 在基础篇中&#xff0c;我给学习者的定位是先上手&#xff0c;能够使用SpringBoot搭建基于SpringBoot的web项目开发&#xff0c;所以内容设置较少&#xff0c;主要包含如下内容&#xff1a; SpringBoot快速入门SpringBoot基础配置基于SpringBoot整合SSMP…

为你的Vue2.x老项目安装Vite发动机吧

天下苦webpack久矣&#xff0c;相信作为前端开发者一定经历过在项目迭代时间较长的时候经历漫长等待的这一过程&#xff0c;每一次保存都会浪费掉大量时间&#xff0c;这是webpack这种机制所带来的问题。 于是&#xff0c;尤大为我们带来了新一代前端构建工具&#xff1a;vite…

搜索旋转排序数组、路径总和 II、拆分数字

文章目录搜索旋转排序数组&#xff08;数组、二分查找&#xff09;路径总和 II&#xff08;树、深度优先搜索&#xff09;拆分数字&#xff08;算法&#xff09;搜索旋转排序数组&#xff08;数组、二分查找&#xff09; 整数数组 nums 按升序排列&#xff0c;数组中的值 互不…

Transformer学习笔记

Transformer学习笔记1. 参考2. 模型图3.encoder部分3.1 Positional Encoding3.2 Muti-Head Attention3.3 ADD--残差连接3.4 Norm标准化3.5 单个Transformer Encoder流程图4.decoder部分4.1 mask Muti-Head Attention4.2 Muti-Head Attention5 多个Transformer Encoder和多个Tra…

详解数据库基本概念

数据库&#xff08;DataBase 简称 DB&#xff09;&#xff1a;是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合数据库管理系统&#xff08;DataBase Management System 简称 DBMS&#xff09;&#xff1a;是一种操纵和管理数据库的大型软件&#xf…

基于嵌入式linux的DHCP服务器的搭建与移植(udhcp)

DHCP是Dynamic Host Configuration Protocol的缩写&#xff0c;即动态主机配置协议。DHCP是一个很重要的局域网的网络协议&#xff0c;使用UDP协议实现动态配置功能&#xff0c;主要有以下用途&#xff1a; 1、为内部网络或网络服务供应商自动分配IP地址&#xff1b; 2、为用…