java8系列-06 时间相关API

image

用过旧版java时间类库的都清楚,其实用起来的感觉是非常糟糕的。比如java.sql.Date与java.util.Date除了包名以外类名都是一样的。(sql.Date是继承util.Date重写的)这种设计其实是非常差的,很容易搞混淆。再比如,当你在并发情景下用java.util.Date是很容易出问题的,因为java.util.Date是属于线程不安全的。针对这些问题,java8推出了一系列新的API. PS: 新的时间相关API都在java.time.*包下

时间日期类

表示时间戳的instant

instant是用来表示时间戳的,等价于System.currentTimeMillis(),instant类被设计成单例模式,使用起来也是极其方便的。

Instant类构建的几种方法以及他们的作用

public class InstantDemo {

    public static void main(String[] args) {
        Instant now = Instant.now(); // return Clock.systemUTC().instant(); 也就是说默认的是格林时区的时间
        System.out.println(now.toEpochMilli());

        // 相对于格林时区偏移八小时,就是中国的上海时区啦
        Instant now2 = Instant.now(Clock.offset(Clock.systemUTC(), Duration.ofHours(8)));
        System.out.println(now2.toEpochMilli());

        Instant from = Instant.from(ZonedDateTime.now()); // 从时态对象(TemporalAccessor接口)获取Instant的实例
        System.out.println(from.toEpochMilli());

        Instant milli = Instant.ofEpochMilli(System.currentTimeMillis()); // 通过毫秒数值直接构建Instant实例
        System.out.println(milli.getEpochSecond());

        Instant second = Instant.ofEpochSecond(60); // 通过传入一个标准时间的偏移值来构建Instant实例
        System.out.println(second);

        Instant second2 = Instant.ofEpochSecond(60,60); // 第二个参数:纳秒调整到秒数,正或负
        System.out.println(second2);

        System.out.println(System.currentTimeMillis());
    }
}

输出

1552128157932
1552156957932
1552128158057
1552128158
1970-01-01T00:01:00Z
1970-01-01T00:01:00.000000060Z
1552128158073

由上可知,Instant默认是基于格林时区的,它可以通过.toEpochMilli()来转换成跟System.currentTimeMillis()一样效果的时间戳格式,当然它也可以直接通过.getEpochSecond()来直接转换成秒的时间戳格式

表示日期的LocalDate

以前的Date类在并发情境下做处理是很容易出现许多问题的(可以开多个线程来玩一下),而LocalDate可以更好的处理这种情况。从源码可以看到这一点: 如final class LocalDate,private LocalDate(){}...,有一点点并发基础的一定懂这些含义。

LocalDate类构建的几种方法以及他们的作用

public class LocalDateDemo {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now(); // 和Instance一样默认的是格林时区
        System.out.println(now);

        LocalDate now2 = LocalDate.now(Clock.offset(Clock.systemUTC(), Duration.ofHours(24))); // 偏移格林时区24小时
        System.out.println(now2);

        LocalDate now3 = LocalDate.now(ZoneId.systemDefault()); // java.time.ZoneId是原有的java.util.TimeZone的替代品
        System.out.println(now3);

        LocalDate from = LocalDate.from(ZonedDateTime.now()); // 从时态对象(TemporalAccessor接口)获取LocalDate的实例
        System.out.println(from);

        LocalDate of = LocalDate.of(2017,5,21); // 参数分别为:year,month,dayOfMonth
        System.out.println(of);

        LocalDate epochDay = LocalDate.ofEpochDay(1800); // 比1970-01-01大多少天
        System.out.println(epochDay);

        LocalDate ofY = LocalDate.ofYearDay(2018,122); // 参数分别为 year , dayOfYear
        System.out.println(ofY);

        LocalDate parse = LocalDate.parse("2018-06-09"); // 字符串转换成LocalDate对象
        System.out.println(parse);
    }
}

输出

2019-03-09
2019-03-10
2019-03-09
2019-03-09
2017-05-21
1974-12-06
2018-05-02
2018-06-09

LocalDate类一些比较有用的方法

  • public int getYear():获取年份信息
  • public int getMonthValue():获取月份信息
  • public int getDayOfMonth():获取当前日是这个月的第几天
  • public int getDayOfYear():获取当前日是这一年的第几天
  • public boolean isLeapYear():是否是闰年
  • public int lengthOfYear():获取这一年有多少天
  • public DayOfWeek getDayOfWeek():返回星期信息
  • public String format(DateTimeFormatter formatter): 格式化LocalDate
  • public LocalDate minusYears(long yearsToSubtract):返回此LocalDate对象,并减去指定的年数。
  • public LocalDate plusDays(long daysToAdd):返回此LocalDate对象,并添加指定的天数。

太多了,这里就不一一列出来了...

时间LocalTime

LocalTime其实与上面的LocalDate类似,只不过LocalTime是来表示时间,而LocalDate是用作日期

LocalTime类构建

public class LocalTimeDemo {
    public static void main(String[] args) {
        LocalTime now = LocalTime.now();
        System.out.println(now); // 输出19:54:31.010
    }
}
  • static LocalTime now():在默认时区中从系统时钟获取当前时间。
  • static LocalTime now(Clock clock):从指定的时钟获得当前时间。
  • static LocalTime now(ZoneId zone):从指定时区的系统时钟获取当前时间。
  • static LocalTime ofNanoOfDay(long nanoOfDay):从一天的纳米值获得LocalTime的实例。
  • static LocalTime from(TemporalAccessor temporal):从temporal对象获取LocalTime的实例。
  • static LocalTime of(int hour, int minute): 从指定小时分钟获得LocalTime的实例。
  • static LocalTime of(int hour, int minute, int second):从指定小时,分钟和秒钟获取LocalTime的实例。
  • static LocalTime of(int hour, int minute, int second, int nanoOfSecond):从指定小时,分钟,秒和纳秒获得LocalTime的实例。
  • static LocalTime parse(CharSequence text):从文本字符串中获取LocalTime的实例。

localTime类的一些方法

public class LocalTimeDemo {
    public static void main(String[] args) {
        LocalTime now = LocalTime.now();
        String minute = now.getMinute()<10?"0"+now.getMinute():String.valueOf(now.getMinute());
        String second = now.getSecond()<10?"0"+now.getSecond():String.valueOf(now.getSecond());
        System.out.println("当前时间:"+now.getHour()+":"+minute+":"+second); //当前时间:20:09:13
        // 获取纳秒字段的值。
        System.out.println(now.getNano()); // 434000000
        // 与另一个时间比较。
        System.out.println(now.compareTo(LocalTime.MAX)); // -1
        // 将日期装换成String
        System.out.println(now.toString()); // 20:09:13.434
        // 将此时间与日期相结合以创建LocalDateTime。
        System.out.println(now.atDate(LocalDate.now())); // 2019-03-09T20:09:13.434
        // 创建一个新的LocalTime,并更改日期。
        System.out.println(now.withHour(8)); // 08:09:13.434
        // 创建一个此时间的偏移时间的LocalTime
        System.out.println(now.atOffset(ZoneOffset.ofHours(8))); // 20:09:13.434+08:00
        // 创建一个此时间加上8小时的Localtime
        System.out.println(now.plusHours(8)); // 04:09:13.434
    }
}

关于LocalTime还有一些其他的方法,请自行研究~~

时区相关的日期时间ZonedDateTime

上面讲的LocalDate、LocalTime还有未讲到的LocalDateTime都是与时区无关的,都只是用的默认时区,而类的本身并没有存储时区。而上面的类要用到时区的话,还需要此类来协助。

public class ZonedDateTimeDemo {
    public static void main(String[] args) {
        ZonedDateTime zdt = ZonedDateTime.now();
        System.out.println(zdt); // 2019-03-09T23:14:48.560+08:00[Asia/Shanghai]

        ZonedDateTime zdt2 = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.of("America/Chicago"));
        System.out.println(zdt2); // 2019-03-09T23:14:48.560-06:00[America/Chicago]

        ZonedDateTime zdt3 = ZonedDateTime.ofInstant(Instant.now(),ZoneId.of("Africa/Cairo"));
        System.out.println(zdt3); // 2019-03-09T17:14:48.591+02:00[Africa/Cairo]
    }
}

解释一下,第一个输出系统默认时区。第二个输出的是没过芝加哥时区,两个参数,第一个是LocalDate,第二个是LocalTime(上面说过这两个类默认是没有任何时区的,想要时区还的结合ZonedDateTime类)。第二个输出是非洲开罗时区,这里传入的参数是时间戳Instant

关于时间的工具类

日期时间格式化

上面讲LocalDate的时候有讲到一个format方法,里面传入的参数是DateTimeFormatter,那这里就讲一下这个类吧。其实也没什么很多要讲的,毕竟它用起来真的太方便啦。一起来看看

public class DateTimeFormatterDemo {

    public static void main(String[] args) {
        LocalDateTime currentTime = LocalDateTime.now();

        // DateTimeFormatter默认规范有很多,这里只列举出了三个
        System.out.println(currentTime.format(DateTimeFormatter.BASIC_ISO_DATE)); // 20190309

        System.out.println(currentTime.format(DateTimeFormatter.ISO_DATE_TIME)); // 2019-03-09T23:39:02.261

        System.out.println(currentTime.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2019-03-09

        System.out.println(currentTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"))); // 20190309
    }
}

真的使用起来太简单了,并且你想要的格式它基本都有

时间差 Period\Duration

1. Period

Period是以年月日来衡量一个时间段,比如几年几月几日

public class PeriodDemo {

    public static void main(String[] args) {
        Period period = Period.of(2018,8,22);
        System.out.println(period);

        System.out.println(Period.between(LocalDate.of(2018,3,5), LocalDate.now()));
    }
}

输出

P2018Y8M22D
P1Y4D
  • P:标识开头
  • Y:年
  • M:月
  • D:日

2. Duration

Duration也是表示一个时间段。不知道各位有没有注意到,其实上面例子中有用到过这个类 Duration.ofHours(8) 向后推迟8小时

public class DurationDemo {
    public static void main(String[] args) {
        LocalDateTime from = LocalDateTime.of(2018,Month.DECEMBER,22,22,33);//2018-12-22T22:33
        LocalDateTime to = LocalDateTime.now(); // 2019-03-10T00:05:42.443
        Duration duration = Duration.between(from, to); // PT1849H33M20.732S

        long days = duration.toDays();              // 这段时间的总天数
        long hours = duration.toHours();            // 这段时间的小时数
        long minutes = duration.toMinutes();        // 这段时间的分钟数
        long seconds = duration.getSeconds();       // 这段时间的秒数
        long milliSeconds = duration.toMillis();    // 这段时间的毫秒数
        long nanoSeconds = duration.toNanos();      // 这段时间的纳秒数
    }
}

其实使用多了这些类你会发现,这些类都有许多的共用。这些我这里就没有总结,请多动手,习惯成自然。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容