日常编程中和日期相关的代码和bug
本文主要是Java中和日期时间相隔的几个常用代码函数代码,做了总结,希望在日常编码中,可以帮到大家。
1.计算闰年
记住一个短语,“四年一润,百年不闰,四百再润”,不管换啥语言,相信大家不会写错这块的实现代码。
怎么理解呢?转换为我们程序语言就是“
- 是4的倍数并且不是100的倍数,那么是普通闰年
- 是400的倍数,那么是世纪闰年
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); 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;public abstract class CustomCountDownTimer { private static final int MSG = 1; private final long mMillisInFuture; private final long mCountdownInterval; private long mStopTimeInFuture; private long mPauseTimeInFuture; private boolean isStop = false; private boolean isPause = false; 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); } 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); } 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,触发一下acceptObservable.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 ,定时周期执行任务。
来源地址:https://blog.csdn.net/baobei0921/article/details/129204144
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341