记得在我刚学Java的时候,真是搞不清楚Date和Calendar这两个类,后来我渐渐知道,原来不能全怪我啊,Java日期API之烂是公认的(不妨参见这篇文章,Tiago Fernandez做过一个投票,就是要选举最烂的Java API,结果Java日期API排行第二,仅次于臭名远扬的EJB2,嘿嘿)。
蛋疼的java.sql.Date
只有Date和Calendar搞定一切吗?那还好啊。当然不是!光Date就有java.util.Date和java.sql.Date,而且关系是java.sql.Date extends java.util.Date。为了把前者转成后者,我写了这样的代码:
1
2
|
Date date = new Date();
java.sql.Date d = new java.sql.Date(date.getTime());
|
居然不支持Date参数的构造器,我只好传入long类型的时间。接下去,我尝试把当前小时数取出来:
1
|
System.out.println(d.getHours()); |
悲剧出现了:
1
2
|
Exception in thread "main" java.lang.IllegalArgumentException at java.sql.Date.getHours(Date.java:177)
|
一看源码,坑爹啊:
1
2
3
|
public int getHours() {
throw new java.lang.IllegalArgumentException();
} |
在java.util.Date里面好好的方法怎么变成这个鸟样了?
方法注释给出了说明:
This method is deprecated and should not be used because SQL Date values do not have a time component.
也就是说,java.sql.Date是SQL中的单纯的日期类型,哪会有时分秒啊?我觉得它根本不应该设计成java.util.Date的子类。如果你把java.sql.Date通过JDBC插入数据库,你会发现时分秒都丢失了,因此如果你同时需要日期和时间,你应该使用Timestamp,它也是java.util.Date的子类。
另外还有一个java.util.Date的子类叫Time,java.sql包下面的Date、Time和Timestamp可以放在一起记忆。Date只包含年月日信息、Time只包含时分秒信息,而Timestamp则包含时间戳的完整信息。
现在知道人家抛出IllegalArgumentException的用心良苦了吧……
坑爹的year和month
看看Date类的构造器:
1
|
public Date( int year, int month, int day)
|
长得并不奇葩嘛。
好,现在我要输出2012年的1月1号了:
1
2
|
Date date = new Date( 2012 , 1 , 1 );
System.out.println(date); |
结果,我傻眼了:
1
|
Thu Feb 01 00:00:00 CST 3912 |
等等,这是啥?3192年?
原来实际年份是要在你的年份参数上加上个起始年份1900。
更坑爹的是,月份参数我不是给了1吗?怎么输出二月(Feb)了?
Date里面的月份居然是用0~11表示的,换句话说,一月用0来表示,二月用1来表示。如果不用常量或者枚举,很容易踩到坑里去,对不对?
后来发现Go语言的time.Date方法,对于月份做了个恶心但是不容易坑人的处理(看奇葩的月份参数啊):
1
|
func Date(year int , month Month, day, hour, min, sec, nsec int , loc *Location)
|
我甚至怀疑Google这样处理是在用极端的方法鄙视Java(另,据我所知,JavaScript好像也是这样的,月份从0开始)……
坑爹的事情还没完,前面已经说了,构造函数的时间起始基准是1900年,可是getTime()方法却特立独行,返回的时间是相对于“1970-01-01 00:00:00”的毫秒数差值……
尝试Joda吧
最开始的时候,Date既要承载日期信息,又要做日期之间的转换,还要做不同日期格式的显示,职责较繁杂,从JDK 1.1 开始,这三项职责分开了:
- 使用Calendar类实现日期和时间字段之间转换;
- 使用DateFormat类来格式化和分析日期字符串;
- 而Date只用来承载日期和时间信息。
原有Date中的相应方法已废弃。不过,无论是Date,还是Calendar,都用着太不方便了,这是API没有设计好的地方。
比如Calendar的getInstance方法,并未提供一个指定年月日和时分秒的重载方法,每次要指定特定的日期时间,必须先获取一个表示当前时间的Calendar实例,再去设值,比如:
1
2
3
|
Calendar c = Calendar.getInstance(); c.set( 2012 , 0 , 1 , 11 , 11 , 11 );
System.out.println(c.getTime()); |
注意上面代码中对于年份的传值——是的,和Date不一样的是,Calendar年份的传值不需要减去1900(当然月份的定义和Date还是一样),这种不一致真是让人抓狂!
打印:
1
|
Sun Jan 01 11:11:11 CST 2012 |
有很多开源库都在努力弥补Java的这一问题,比如Joda-Time,获取Calendar对象和设置时间完全可以合成一步完成:
1
|
DateTime dateTime = new DateTime( 2012 , 1 , 1 , 11 , 11 , 11 , 0 );
|
而且,一月份总是可以传1来表示了。
再如,如果要给上述时间增加3天再按格式输出的话,使用Joda更加便捷:
1
|
System. out .println(dateTime.plusDays(3).toString( "E MM/dd/yyyy HH:mm:ss" );
|
有兴趣的话请阅读此文,并下载Joda-Time使用。
JSR-310
众所周知Java的规范就是多、而且啰嗦,这帮老大们(Export Group中除了有Oracle的人,还有IBM、Google和RedHat的人)终于再也无法忍受Java那么烂的日期API了,于是就有了JSR-310(感兴趣的请移步),官方的描述叫做“This JSR will provide a new and improved date and time API for Java.”,目前的阶段还在“Early Draft Review 2”,有得等。
JSR-310将解决许多现有Java日期API的设计问题。比如Date和Calendar目前是可变对象,你可以随意改变对象的日期或者时间,而Joda就将DateTime对象设计成String对象一样地不可变,能够带来线程安全等等的好处,因此这一点也将被JSR-310采纳。
很多JSR规范都是在程序员的诋毁和谩骂声中萌芽的,然后会有开源项目来尝试解决Java的这些弊端,最后就轮到JSR就去抄他们的实现。除了新的日期API,再比如JCache(JSR-107),你知道它抄了多少EhCache的东西么……
相关推荐
本文档是 Java 2 Platform Standard Edition 6.0 的 API 规范。 请参见: 描述 Java 2 Platform 软件包 java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含...
5. **日期和时间API**: Java 8引入了`java.time`包,提供`LocalDate`、`LocalTime`、`LocalDateTime`等类,替代了原有的`java.util.Date`和`Calendar`,使日期和时间的操作更加直观。 **模块系统(Project Jigsaw)...
Java 8中引入了新的日期时间API,包括java.time包下的LocalDate、LocalTime、LocalDateTime和ZonedDateTime等类,替代了原有的Calendar和Date。这些新类提供了更强大、更直观的时间日期处理能力。 六、方法引用和...
Java 8还对日期和时间API进行了重写,引入了`java.time`包。旧的`java.util.Date`和`java.util.Calendar`被更直观、更易用的`LocalDate`、`LocalTime`、`LocalDateTime`等类取代。这些新类提供了更丰富的操作和格式...
6. **日期和时间**:在Java 1.6中,`java.util.Date`和`Calendar`类是处理日期和时间的主要工具,虽然在后续版本中被`java.time`包中的新API取代,但在1.6版本中仍然广泛使用。 7. **反射**:`java.lang.reflect`包...
JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-API-1.8`JAVA-...
8. **日期时间**:Java 8引入了新的日期和时间API(java.time包),包括LocalDate、LocalTime、LocalDateTime等类,提供了更直观和强大的日期时间处理功能。 9. **国际化与本地化**:java.util.Locale和...
5. **日期和时间API**:Java 8用`java.time`包取代了过时的`java.util.Date`和`Calendar`,提供了更直观和易用的日期、时间和时区处理。`LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`等类提供了丰富...
- **日期和时间API**:用`java.time`包取代了`java.util.Date`和`java.util.Calendar`,提供了更直观、更强大的日期和时间操作。 - **默认方法**:在接口中可以定义默认实现的方法,使得接口升级时避免破坏现有...
- **日期和时间**:`Date`, `Calendar`类以及Java 7新增的`java.time`包,提供了处理日期和时间的工具,如`LocalDate`, `LocalTime`, `DateTimeFormatter`等。 - **反射**:`Class`, `Method`, `Field`等类提供了...
Java API文档是Java开发者不可或缺的参考资料,它详细记录了Java编程语言的标准库,包括类、接口、方法和属性等核心元素。这些文档不仅提供技术规格,还包含使用示例,帮助程序员理解和应用Java的各类功能。 1. **...
Java API文档是Java开发者的重要参考资料,它包含了Java开发工具包(JDK)中的所有类、接口、方法和常量的详细说明。这份中文网页版的Java API文档为中国的开发者提供了便利,无需通过英文版本来学习和查找API信息,...
open CV2.9.4版本的java ApI
`java.util`包含集合框架、日期时间、随机数生成等;`java.io`则涉及输入/输出流操作。 2. **网络编程**:`java.net`包提供了网络通信的支持,包括Socket和ServerSocket类,用于实现客户端和服务器端的连接。 3. *...
标题《ElasticSearch Java API 中文文档》表明本篇文档的主要内容是关于ElasticSearch的Java API的中文使用说明和相关知识点介绍。ElasticSearch是一个基于Lucene构建的开源搜索引擎,它提供了一个分布式、多用户...
**JAVA 1.8 API官方文档中文版** Java 1.8 API官方文档是Java开发者不可或缺的参考资料,它详尽地介绍了Java开发平台的核心类库,涵盖了从基本数据类型、对象创建到高级特性如多线程、网络编程、I/O流、反射、泛型...
Java调用Jenkins API是一个常见的自动化任务执行场景,特别是在持续集成和持续部署(CI/CD)流程中。Jenkins作为一个开源的持续集成工具,提供了丰富的API接口,允许开发者通过编程方式与Jenkins服务器进行交互。...
4. **日期与时间API**:Java 8对日期和时间的处理进行了全面改进,`java.time`包取代了旧的`java.util.Date`和`java.util.Calendar`,提供了更加直观和强大的日期/时间操作。 5. **Optional类**:`Optional<T>`是一...
8. **日期和时间API**:Java 8引入了全新的`java.time`包,取代了过时的`java.util.Date`和`java.util.Calendar`,提供更加友好和强大的日期、时间、时区处理能力。 9. **XML处理**:`javax.xml`包提供了解析和生成...
Java日期API是Java编程语言中处理日期和时间的核心库,它允许开发者进行各种日期和时间相关的操作。在Java的历史发展中,日期API经历了多次迭代,从早期的`java.util.Date`和`java.text.SimpleDateFormat`,到Java 8...