百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

月光宝盒之时间魔法--java时间处理的前生今世

toyiye 2024-06-21 12:18 10 浏览 0 评论

月光宝盒花絮

“曾经有一份真诚的爱情摆在我的面前,但是我没有珍惜,等到了失去的时候才后悔莫及,尘世间最痛苦的事莫过于此。如果可以给我一个机会再来一次的话,我会跟那个女孩子说我爱她,如果非要把这份爱加上一个期限,我希望是一万年!”---大话西游之仙履奇缘

《大话西游之大圣娶亲》(又名《大话西游之仙履奇缘》)是周星驰彩星电影公司1994年制作和出品的一部经典的无厘头搞笑爱情片,改编依据是吴承恩所撰写的神怪小说《西游记》,该片是《大话西游》系列的第二部,由刘镇伟导演,技安编剧,周星驰制作,周星驰、朱茵、莫文蔚、蔡少芬、陆树铭、吴孟达等人主演。

该片主要讲述了至尊宝为了救白晶晶而穿越回到五百年前,遇见紫霞仙子之后发生一段感情并最终成长为孙悟空的故事。该片于1995年2月4日在香港首映并入围第十五届香港电影金像奖最佳编剧奖和最佳男主角奖,周星驰凭借该片获得第一届香港电影金紫荆奖最佳男主角奖和第二届香港电影评论学会奖最佳男主角奖。

java中关于时间的设计经历了Date,Calendar,到最后引用第三方包joda time,都发生了什么?让我们看看吧

java时间前生之Date

在Java平台首次发布时,它唯一支持日历计算类的就是Date 类。这个类在能力方面是受限的,特别是当需要支持国际化时,它就暴露出了一个基本的设计缺陷:Date实例是易变的。Date会产生什么问题呢?请看一下下面程序的输出:

	public static void main(String[] args) {
		Date date=new Date(2018,12,31,0,0,0);		
		System.out.println(date.getYear());
		System.out.println(date.getMonth());
		System.out.println(date.getDay());
	}

我们想打印出的结果是

2018

12

31

可是,运行后的结果打印

2019

0

5

穿越了吗?还是我的机器有问题?

换了别的机器依然如此。只好进源码看看

 /**
 * Allocates a <code>Date</code> object and initializes it so that
 * it represents the instant at the start of the minute specified by
 * the <code>year</code>, <code>month</code>, <code>date</code>,
 * <code>hrs</code>, and <code>min</code> arguments, in the local
 * time zone.
 *
 * @param year the year minus 1900.
 * @param month the month between 0-11.
 * @param date the day of the month between 1-31.
 * @param hrs the hours between 0-23.
 * @param min the minutes between 0-59.
 * @see java.util.Calendar
 * @deprecated As of JDK version 1.1,
 * replaced by <code>Calendar.set(year + 1900, month, date,
 * hrs, min)</code> or <code>GregorianCalendar(year + 1900,
 * month, date, hrs, min)</code>.
 */
 @Deprecated
 public Date(int year, int month, int date, int hrs, int min) {
 this(year, month, date, hrs, min, 0);
 }

程序大揭秘:

  1. 设置年份是从1900开始的,即2018-1900=118
  2. 设置月份是从0开始的,即0~11,12等于下一年119年的第一个月即值为0
  3. day返回的是是周几
 /**
 * Returns the day of the week represented by this date. The
 * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday,
 * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> =
 * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday)
 * represents the day of the week that contains or begins with
 * the instant in time represented by this <tt>Date</tt> object,
 * as interpreted in the local time zone.
 *
 * @return the day of the week represented by this date.
 * @see java.util.Calendar
 * @deprecated As of JDK version 1.1,
 * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>.
 */
 @Deprecated
 public int getDay() {
 return normalize().getDayOfWeek() - BaseCalendar.SUNDAY;
 }

java时间前生之Calenar

在1.1 版中,Calendar 类被添加到了Java 平台中,以矫正Date的缺点,由此大部分的Date 方法就都被弃用了。遗憾的是,这么做只能使情况更糟。我们的程序说明Date 和Calendar API 有许多问题。

	public static void main(String[ ] args) {
		Calendar cal = Calendar.getInstance();
		cal.set(2018, 12, 31); // Year, Month, Day
		System.out.print(cal.get(Calendar.YEAR) + " ");
		Date d = cal.getTime();
		System.out.println(d.getDay());
		}

来干活吧,运行输出结果:

2019 4

进源码看看吧

 /**
 * Sets the values for the calendar fields <code>YEAR</code>,
 * <code>MONTH</code>, and <code>DAY_OF_MONTH</code>.
 * Previous values of other calendar fields are retained. If this is not desired,
 * call {@link #clear()} first.
 *
 * @param year the value used to set the <code>YEAR</code> calendar field.
 * @param month the value used to set the <code>MONTH</code> calendar field.
 * Month value is 0-based. e.g., 0 for January.
 * @param date the value used to set the <code>DAY_OF_MONTH</code> calendar field.
 * @see #set(int,int)
 * @see #set(int,int,int,int,int)
 * @see #set(int,int,int,int,int,int)
 */
 public final void set(int year, int month, int date)
 {
 set(YEAR, year);
 set(MONTH, month);
 set(DATE, date);
 }

从上面的理解中,月份是从0开始的即0~11 代表 1月。。。。。12月

接着date又是从1开始的,为什么同一个方法设计的如此怪异?

程序揭秘

1.标准的(西历)日历只有12 个月,该方法调用肯定应该抛出一IllegalArgumentException 异常,对吗?它是应该这么做,但是它并没有这么做。Calendar 类直接将其替换为下一年,即:2019

有两种方法可以订正这个问题。你可以将cal.set 调用的第二个参数由12 改为11,但是这么做容易引起混淆,因为数字11 会让读者误以为是11 月。更好的方式是使用Calendar 专为此目的而定义的常量,即Calendar.DECEMBER

2. Date.getDay 返回的是Date实例所表示的星期日期,而不是月份日期。这个返回值是基于0 的,从星期天开始计算,即:4

有两种方法可以订正这个问题。你可以调用Date.date 这一名字极易让人混淆的方法,它返回的是月份日期。然而,与大多数Date 方法一样,它已经被弃用了,

因此你最好是将Date 彻底抛弃,直接调用Calendar 的get(Calendar.DAY_OF_MONTH)方法。

上例只是掀开了Calendar 和Date 缺陷的冰山一角。这些API 简直就是雷区。Calendar 其他的严重问题包括弱类型(几乎每样事物都是一个int)、过于复杂的状态空间、拙劣的结构、不一致的命名以及不一致的雨衣等。在使用Calendar和Date 的时候一定要当心,千万要记着查阅API 文档。

对API 设计者来说,其教训是:如果你不能在第一次设计时就使它正确,那么至少应该在第二次设计时应该使它正确,绝对不能留到第三次设计时去处理。如果你对某个API 的首次尝试出现了严重问题,那么你的客户可能会原谅你,并且会再给你一次机会。如果你第二次尝试又有问题,你可能会永远坚持这些错误了。

java时间后世之Joda Time

JDK在8之前的版本,对日期时间的处理相当麻烦,有些方法设计非常反人类。而Joda-Time使用起来不仅方便,而且可读性强。虽然JDK 8引用了新的时间处理类,而且参与设计的人也正是Joda-Time的作者,但是由于各种原因,很多项目还是使用的JDK7,使用Joda-Time还是一个不错的选择。

Joda-Time提供了一组Java类包用于处理包括ISO8601标准在内的date和time。可以利用它把JDK Date和Calendar类完全替换掉,而且仍然能够提供很好的集成。

Joda-Time主要的特点包括:

1. 易于使用:Calendar让获取"正常的"的日期变得很困难,使它没办法提供简单的方法,而Joda-Time能够 直接进行访问域并且索引值1就是代表January。

2. 易于扩展:JDK支持多日历系统是通过Calendar的子类来实现,这样就显示的非常笨重而且事实 上要实现其它日历系统是很困难的。Joda-Time支持多日历系统是通过基于Chronology类的插件体系来实现。

3. 提供一组完整的功能:它打算提供 所有关系到date-time计算的功能.Joda-Time当前支持8种日历系统,而且在将来还会继续添加,有着比JDK Calendar更好的整体性能等等。

joda time示例

//jdk 
Calendar calendar=Calendar.getInstance(); 
calendar.set(2012, Calendar.NOVEMBER, 15, 18, 23,55); 
 
//Joda-time 
DateTime dateTime=new DateTime(2012, 12, 15, 18, 23,55); 

更详细的参考:https://www.joda.org/joda-time/

参考资料:

【1】https://www.iteye.com/blog/persevere-1755237

【2】java解惑

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码