JAVA TIME API总结

这两天看了几篇这方面文章,觉得很不错,特别记录一下(大概我也很弱,对这方面踩的坑不多)


本文参考了 闲谈为什么慎用 Date全面掌握 Java 时间日期 API ,感谢两位作者

旧API的坑

    @Test
	public void test1() {
		Date date = new Date();// Date date = new Date(System.currentTimeMillis()); // 与上等价System.out.println(date);

		Date date1 = new Date(System.currentTimeMillis());
		
		System.out.println(date.getYear() + "-" + date.getMonth() + "-" + date.getDay());

		System.out.println(date.getDate());
		
		System.out.println(date.getDay());
		
		System.out.println(date1);
	}
	结果:
    119-0-3
    9 //第九天
    3 //第三周
    Wed Jan 09 16:02:14 CST 2019

查阅博客资料,原来年份的值是当前年份距离1900年在数值上的差值(这一点 Java 参考了 C),月份是从 0 开始计算的(这一点也是参考了 C),而当前日的取值笔者使用的是 getDay(),它的取值是 day-of-week,实际上 Date 还提供了 getDate(),它的取值是 day-of-month。

Date的问题

Date 这个类给开发者的第一印象应该是日期,也就是记录到年月日的一个类,但是注释里面却提到

The class Date represents a specific instant in time, with millisecond precision.

  1. 这其实说明Date是时间轴上的一个瞬间,按理说是夜歌不可变类,就和String一样。
    但是与此同时 Date 类竟然并不是 final 的,这意味着开发者还可以通过 setTime() 去改变「瞬间」

  2. 衡量一个瞬间除了记录年月日时分秒之外,还应该记录时区,但是 Date 对象中并没有包含时区这个关键属性,而仅仅是在 toString() 方法中 new 了一个时区对象并打印出来,这明显是不符合常理的。实际上由于标toString()方法按照JVM的默认时区输出时间和日期,有些开发人员把它误认为是时区敏感的。

然后旧的日期 API 中 Date 有 java.util.Date 和 java.sql.Date,两者的关系是 java.sql.Date 继承 java.util.Date(这个以前还真没有注意过)。为了把前者转成后者,需要使用如下代码:

	@Test
	public void test2() {
		Date date = new Date();
		java.sql.Date d = new java.sql.Date(date.getTime());
		//System.out.println(d.getHours()); 报错
		//System.out.println(d.getMinutes()); 报错
		System.out.println(d.getSeconds()); 报错
	}
	结果呢:
	报错
	Exception in thread "main" java.lang.IllegalArgumentException

java.sql.Date 是 SQL 中的单纯的日期类型,不会有时分秒,这就是为什么把 java.sql.Date 通过 JDBC 插入数据库,会发现时分秒都没有了(匪夷所思)。因此如果你同时需要日期和时间,你应该使用 Timestamp,它也是 java.util.Date 的子类,Timestamp 则包含时间戳的完整信息。
3. Data 这个类扮演着诸多角色,它提供了操作时刻的方法,提供了操作年月日日期的方法,甚至还有关时区的方法。就是职责过宽,导致什么也做不好
4. 还有类似线程安全的问题,比如simpleDateformat问题

Joda_Time

老实说,上个小项目,我才开始用这个库,的确很香!计算时间的时候真的是简洁!
特点如下:

  • 不可变性: Joda 类具有不可变性,因此它们的实例无法被修改。(不可变类的一个优点就是它们是线程安全的)
  • 瞬间性: Instant 表示时间上的某个精确的时刻,使用从 epoch 开始计算的毫秒表示。这一定义与 JDK 相同,这就是为什么任何 Joda Instant 子类都可以与 JDK Date 和 Calendar 类兼容的原因
  • 时区: DateTimeZone 是 Joda 库用于封装位置概念的类。许多日期和时间计算都可以在不涉及时区的情况下完成,但是仍然需要了解 DateTimeZone如何影响 Joda 的操作
最重要的一点,可以与JDK中的Date api兼容!!!
Date date = dateTime.toDate();
Calendar calendar = dateTime.toCalendar(Locale.CHINESE);

//通过jdk时间对象构造  
Date date = new Date();  
DateTime dateTime = new DateTime(date);  

Calendar calendar = Calendar.getInstance();  
dateTime = new DateTime(calendar); 

然后后面贴一下网上找的demo

package com.bijian.study;  
  
import java.util.Calendar;  
import java.util.Date;  
import java.util.Locale;  
import org.joda.time.DateTime;  
import org.joda.time.Days;  
import org.joda.time.LocalDate;  
import org.joda.time.format.DateTimeFormat;  
import org.joda.time.format.DateTimeFormatter;  
  
public class JodaTest {  
  
    public static void main(String[] args) {  
        // 初始化时间  
        DateTime dateTime = new DateTime(2012, 12, 13, 18, 23, 55);  
  
        // 年,月,日,时,分,秒,毫秒  
        DateTime dt3 = new DateTime(2011, 2, 13, 10, 30, 50, 333);
        // 2010年2月13日10点30分50秒333毫秒  
  
        // 下面就是按照一点的格式输出时间  
        String str2 = dateTime.toString("MM/dd/yyyy hh:mm:ss.SSSa");  
        String str3 = dateTime.toString("dd-MM-yyyy HH:mm:ss");  
        String str4 = dateTime.toString("EEEE dd MMMM, yyyy HH:mm:ssa");  
        String str5 = dateTime.toString("MM/dd/yyyy HH:mm ZZZZ");  
        String str6 = dateTime.toString("MM/dd/yyyy HH:mm Z");  
  
        DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");  
        // 时间解析  
        DateTime dateTime2 = DateTime.parse("2012-12-21 23:22:45", format);  
  
        // 时间格式化,输出==> 2012/12/21 23:22:45 Fri  
        String string_u = dateTime2.toString("yyyy/MM/dd HH:mm:ss EE");  
        System.out.println(string_u);  
  
        // 格式化带Locale,输出==> 2012年12月21日 23:22:45 星期五  
        String string_c = dateTime2.toString("yyyy年MM月dd日 HH:mm:ss EE",  
                Locale.CHINESE);  
        System.out.println(string_c);  
  
        DateTime dt1 = new DateTime();// 取得当前时间  
  
        // 根据指定格式,将时间字符串转换成DateTime对象,这里的格式和上面的输出格式是一样的  
        DateTime dt2 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")  
                .parseDateTime("2012-12-26 03:27:39");  
  
        // 计算两个日期间隔的天数  
        LocalDate start = new LocalDate(2012, 12, 14);  
        LocalDate end = new LocalDate(2013, 01, 15);  
        int days = Days.daysBetween(start, end).getDays();  
  
        // 计算两个日期间隔的小时数,分钟数,秒数  
  
        // 增加日期  
        DateTime dateTime1 = DateTime.parse("2012-12-03");  
        dateTime1 = dateTime1.plusDays(30);  
        dateTime1 = dateTime1.plusHours(3);  
        dateTime1 = dateTime1.plusMinutes(3);  
        dateTime1 = dateTime1.plusMonths(2);  
        dateTime1 = dateTime1.plusSeconds(4);  
        dateTime1 = dateTime1.plusWeeks(5);  
        dateTime1 = dateTime1.plusYears(3);  
  
        // Joda-time 各种操作.....  
        dateTime = dateTime.plusDays(1) // 增加天  
                .plusYears(1)// 增加年  
                .plusMonths(1)// 增加月  
                .plusWeeks(1)// 增加星期  
                .minusMillis(1)// 减分钟  
                .minusHours(1)// 减小时  
                .minusSeconds(1);// 减秒数  
  
        // 判断是否闰月  
        DateTime dt4 = new DateTime();  
        org.joda.time.DateTime.Property month = dt4.monthOfYear();  
        System.out.println("是否闰月:" + month.isLeap());  
  
        // 取得 3秒前的时间  
        DateTime dt5 = dateTime1.secondOfMinute().addToCopy(-3);  
        dateTime1.getSecondOfMinute();// 得到整分钟后,过的秒钟数  
        dateTime1.getSecondOfDay();// 得到整天后,过的秒钟数  
        dateTime1.secondOfMinute();// 得到分钟对象,例如做闰年判断等使用  
  
        // DateTime与java.util.Date对象,当前系统TimeMillis转换  
        DateTime dt6 = new DateTime(new Date());  
        Date date = dateTime1.toDate();  
        DateTime dt7 = new DateTime(System.currentTimeMillis());  
        dateTime1.getMillis();  
  
        Calendar calendar = Calendar.getInstance();  
        dateTime = new DateTime(calendar);  
    }  
}  
结果:
2012/12/21 23:22:45 星期五  
2012122123:22:45 星期五  
是否闰月:true  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值