Java使用Joda-Time处理日期和时间

2024-04-25 18:58

本文主要是介绍Java使用Joda-Time处理日期和时间,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Java使用Joda-Time处理日期和时间

  • 1. Maven配置
  • 2. Joda-Time微架构
  • 3. 初识 org.joda.time.DateTime
  • 4. 创建Joda-Time
    • 4.1 获取当前系统时间
    • 4.2 通过给定的毫秒值创建
    • 4.3 通过给定的对象创建
    • 4.4 通过指定字段值创建
  • 5. Joda-Time日期操作
  • 6. Joda-Time日期格式化
  • 7. 一些源码
    • 7.1 计算指定年的毫秒数的方法
    • 7.2 将UTC毫秒数切换成本地时区对应的毫秒数
  • 8. 功能示例
    • 8.1 获取本周的开始日期和结束日期
    • 8.2 获取当前日期的所属周
    • 8.3 日期格式化和解析
  • 参考

1. Maven配置

<dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10</version>
</dependency>

2. Joda-Time微架构

在这里插入图片描述

3. 初识 org.joda.time.DateTime

通过org.joda.time.DateTime的类图我们可以看到,其核心的Field主要是iMillis和iChronology。DateTime的核心是UTC 1970年1月1日以来的毫秒值 iMillis,而所有对日期的操作通过 年表 iChronology 来实现。从根本上讲,年表是一种日历系统 — 一种计算时间的特殊方式 — 并且是一种在其中执行日历算法的框架。

org.joda.time.base.BaseDateTime

    /** The millis from 1970-01-01T00:00:00Z */private volatile long iMillis;/** The chronology to use */private volatile Chronology iChronology;

目前Joda-Time提供8种日历系统:

  • Buddhist
  • Coptic
  • Ethiopic
  • Gregorian-Julian cutover
  • Gregorian
  • Islamic
  • ISO(Default)- ISO8601
  • Julian

图1 org.joda.time.DateTime的类图
org.joda.time.DateTime的类图
图2 年表核心类图

org.joda.time.chrono.AssembledChronology

Abstract Chronology that enables chronologies to be assembled from a container of fields.

org.joda.time.chrono.ZonedChronology

Wraps another Chronology to add support for time zones.

org.joda.time.chrono.ZonedChronology.ZonedDateTimeField

A DateTimeField that decorates another to add timezone behaviour.

org.joda.time.chrono.ISOChronology

Implements a chronology that follows the rules of the ISO8601 standard, which is compatible with Gregorian for all modern dates.

org.joda.time.chrono.GregorianChronology

Implements a pure proleptic Gregorian calendar system, which defines every fourth year as leap, unless the year is divisible by 100 and not by 400. This improves upon the Julian calendar leap year rule.

在这里插入图片描述

4. 创建Joda-Time

4.1 获取当前系统时间

其核心是通过 java.lang.System#currentTimeMillis 获取系统当前毫秒值。相关构造方法:

  • org.joda.time.DateTime#DateTime()
  • org.joda.time.DateTime#DateTime(org.joda.time.DateTimeZone)
  • org.joda.time.DateTime#DateTime(org.joda.time.Chronology)

4.2 通过给定的毫秒值创建

相关构造方法:

  • org.joda.time.DateTime#DateTime(long)
  • org.joda.time.DateTime#DateTime(long, org.joda.time.DateTimeZone)
  • org.joda.time.DateTime#DateTime(long, org.joda.time.Chronology)

4.3 通过给定的对象创建

解析给定对象,并转换成Joda-Time对象。支持的对象包括java.util.Calendar, java.lang.Long, java.lang.String, java.util.Date, org.joda.time.ReadableInstant等。其中转换通过对象转换器实现,公共接口为org.joda.time.convert.InstantConverter

  • org.joda.time.DateTime#DateTime(java.lang.Object)
  • org.joda.time.DateTime#DateTime(java.lang.Object, org.joda.time.DateTimeZone)
  • org.joda.time.DateTime#DateTime(java.lang.Object, org.joda.time.Chronology)

4.4 通过指定字段值创建

通过制定年、月、日、时、分、秒、毫秒值创建对象。

  • org.joda.time.DateTime#DateTime(int, int, int, int, int, int, int)
  • org.joda.time.DateTime#DateTime(int, int, int, int, int, int, int, org.joda.time.DateTimeZone)
  • org.joda.time.DateTime#DateTime(int, int, int, int, int, int, int, org.joda.time.Chronology)

5. Joda-Time日期操作

Joda-Time对日期的操作是通过org.joda.time.DateTime.Property来实现的,Property将DateTime与日历系统的org.joda.time.DateTimeField进行绑定,并最终通过DateTimeField的操作来实现对日期的操作。

以下摘录自org.joda.time.DateTime.Property的JavaDoc。

DateTime.Property binds a DateTime to a DateTimeField allowing powerful datetime functionality to be easily accessed.
The simplest use of this class is as an alternative get method, here used to get the year ‘1972’ (as an int) and the month ‘December’ (as a String).
DateTime dt = new DateTime(1972, 12, 3, 0, 0, 0, 0);
int year = dt.year().get();
String monthStr = dt.month().getAsText();

Methods are also provided that allow date modification. These return new instances of DateTime - they do not modify the original.
The example below yields two independent immutable date objects 20 years apart.
DateTime dt = new DateTime(1972, 12, 3, 0, 0, 0, 0);
DateTime dt20 = dt.year().addToCopy(20);

Serious modification of dates (ie. more than just changing one or two fields) should use the MutableDateTime class.
DateTime.Propery itself is thread-safe and immutable, as well as the DateTime being operated on.

6. Joda-Time日期格式化

根据格式化pattern创建org.joda.time.format.DateTimeFormatter
根据时区调整Joda-Time(变更毫秒值)
调用日历系统获取各字段值,构建格式化日期串

org.joda.time.format.DateTimeFormatterBuilder.Composite#printTo(java.lang.Appendable, long, org.joda.time.Chronology, int, org.joda.time.DateTimeZone, java.util.Locale)

		public void printTo(Appendable appendable, long instant, Chronology chrono,int displayOffset, DateTimeZone displayZone, Locale locale) throws IOException {InternalPrinter[] elements = iPrinters;if (elements == null) {throw new UnsupportedOperationException();}if (locale == null) {// Guard against default locale changing concurrently.locale = Locale.getDefault();}int len = elements.length;for (int i = 0; i < len; i++) {elements[i].printTo(appendable, instant, chrono, displayOffset, displayZone, locale);}}

7. 一些源码

7.1 计算指定年的毫秒数的方法

org.joda.time.chrono.GregorianChronology#calculateFirstDayOfYearMillis

	long calculateFirstDayOfYearMillis(int year) {// Initial value is just temporary.int leapYears = year / 100;if (year < 0) {// Add 3 before shifting right since /4 and >>2 behave differently// on negative numbers. When the expression is written as// (year / 4) - (year / 100) + (year / 400),// it works for both positive and negative values, except this optimization// eliminates two divisions.leapYears = ((year + 3) >> 2) - leapYears + ((leapYears + 3) >> 2) - 1;} else {leapYears = (year >> 2) - leapYears + (leapYears >> 2);if (isLeapYear(year)) {leapYears--;}}return (year * 365L + (leapYears - DAYS_0000_TO_1970)) * DateTimeConstants.MILLIS_PER_DAY;}

7.2 将UTC毫秒数切换成本地时区对应的毫秒数

org.joda.time.DateTimeZone#convertUTCToLocal

/*** Converts a standard UTC instant to a local instant with the same* local time. This conversion is used before performing a calculation* so that the calculation can be done using a simple local zone.** @param instantUTC  the UTC instant to convert to local* @return the local instant with the same local time* @throws ArithmeticException if the result overflows a long* @since 1.5*/public long convertUTCToLocal(long instantUTC) {int offset = getOffset(instantUTC);long instantLocal = instantUTC + offset;// If there is a sign change, but the two values have the same sign...if ((instantUTC ^ instantLocal) < 0 && (instantUTC ^ offset) >= 0) {throw new ArithmeticException("Adding time zone offset caused overflow");}return instantLocal;}

8. 功能示例

8.1 获取本周的开始日期和结束日期

	@Testpublic void week() {// 获取当前日期DateTime dateTime = new DateTime();String pattern = "yyyy-MM-dd HH:mm:ss";// 本周开始时间 00:00:00String monday = dateTime.dayOfWeek().withMinimumValue().withTimeAtStartOfDay().toString(pattern);// 本周结束时间 23:59:59String sunday = dateTime.dayOfWeek().withMaximumValue().millisOfDay().withMaximumValue().toString(pattern);System.out.println(monday);System.out.println(sunday);}

8.2 获取当前日期的所属周

	@Testpublic void getWeek() {// 创建DateTimeDateTime dateTime = new DateTime(2018, 12, 31, 0, 0, 0);// 获取年int weekyear = dateTime.getWeekyear();// 获取周int weekOfWeekyear = dateTime.getWeekOfWeekyear();// 结果:1System.out.println(weekyear);// 结果:2019System.out.println(weekOfWeekyear);}

8.3 日期格式化和解析

    @Testpublic void format() {// toStringString date = new DateTime().toString("yyyy-MM-dd");System.out.println(date);}@Testpublic void parse() {// create formatterDateTimeFormatter formater = DateTimeFormat.forPattern("yyyy-MM-dd");// parse date stringDateTime dateTime = formater.parseDateTime("2019-04-25");// 2019-04-25T00:00:00.000+08:00System.out.println(dateTime);}

参考

Joda-Time 简介
Calendar systems
joda-time

这篇关于Java使用Joda-Time处理日期和时间的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/935516

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程