Java常用API(二)

9.4.2 第二代日期时间(JDK1.1)

1、java.util.TimeZone

通常,使用 getDefault 获取 TimeZonegetDefault 基于程序运行所在的时区创建 TimeZone

也可以用 getTimeZone 及时区 ID 获取 TimeZone 。例如美国太平洋时区的时区 ID 是 "America/Los_Angeles"。

时区.gif
package com.atguigu.datetime.two;
import org.junit.Test;
import java.util.TimeZone;
public class TestTimeZone {
    @Test
    public void test1(){
        TimeZone t = TimeZone.getDefault();
        System.out.println(t);
    }
    @Test
    public void test2(){
        TimeZone t = TimeZone.getTimeZone("UTC");
        System.out.println(t);
    }
    @Test
    public void test3(){
        TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
        System.out.println(t);
    }
    @Test
    public void test4(){
        String[] all = TimeZone.getAvailableIDs();
        for (int i = 0; i < all.length; i++) {
            System.out.println(all[i]);
        }
    }
}

常见时区ID:

Asia/Shanghai
UTC
America/New_York
America/Los_Angeles

2、java.util.Locale

Locale 对象表示了特定的地理、政治和文化地区。需要 Locale 来执行其任务的操作称为*语言环境敏感的* 操作,它使用 Locale 为用户量身定制信息。

语言参数是一个有效的 **ISO 语言代码**。这些代码是由 ISO-639 定义的小写两字母代码。

国家/地区参数是一个有效的 **ISO 国家/地区代码**。这些代码是由 ISO-3166 定义的大写两字母代码。

Locale 类提供了一些方便的常量,可用这些常量为常用的语言环境创建 Locale 对象。

import org.junit.Test;
import java.util.Locale;
public class TestLocale {
    @Test
    public void test01(){
        Locale[] all = Locale.getAvailableLocales();
        for (int i = 0; i < all.length; i++) {
            System.out.println(all[i]);
        }
    }
    
    @Test
    public void test02(){
        Locale china = Locale.CHINA;
        System.out.println("china = " + china);
    }
}

3、java.util.Calendar

Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEARMONTHDAY_OF_MONTHHOUR日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距*历元*(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。与其他语言环境敏感类一样,Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。

image-20220123184906903-16769854303492.png

修改和获取 YEARMONTHDAY_OF_MONTHHOUR日历字段对应的时间值。

void add(int field,int amount)
int get(int field)
void set(int field, int value)  

示例代码:

package com.atguigu.datetime.two;
import org.junit.Test;
import java.util.Calendar;
import java.util.TimeZone;
public class TestCalendar {
    @Test
    public void test1(){
        Calendar c = Calendar.getInstance();
        System.out.println(c);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
    }
    @Test
    public void test2(){
        TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
        
        Calendar c = Calendar.getInstance(t);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
    }
}

9.4.3 第三代日期时间(JDK1.8)

Java1.0中包含了一个Date类,但是它的大多数方法已经在Java 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:

  • 可变性:像日期和时间这样的类对象应该是不可变的。Calendar类中可以使用三种方法更改日历字段:set()、add() 和 roll()。
  • 偏移性:Date中的年份是从1900开始的,而月份都是从0开始的。
  • 格式化:格式化只对Date有用,Calendar则不行。
  • 此外,它们也不是线程安全的,不能处理闰秒等。

可以说,对日期和时间的操作一直是Java程序员最痛苦的地方之一。第三次引入的API是成功的,并且java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。

Java 8 吸收了 Joda-Time的精华,以一个新的开始为 Java 创建优秀的 API。

  • java.time – 包含值对象的基础包
  • java.time.chrono – 提供对不同的日历系统的访问。
  • java.time.format – 格式化和解析时间和日期
  • java.time.temporal – 包括底层框架和扩展特性
  • java.time.zone – 包含时区支持的类

Java 8 吸收了 Joda-Time的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于时钟(Clock),本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。

1、本地日期时间:LocalDate、LocalTime、LocalDateTime

序号方法描述
1now() / now(ZoneId zone)静态方法,根据当前时间创建对象/指定时区的对象
2of()静态方法,根据指定日期/时间创建对象
3getDayOfMonth()/getDayOfYear()获得月份天数(1-31) /获得年份天数(1-366)
4getDayOfWeek()获得星期几(返回一个 DayOfWeek 枚举值)
5getMonth()获得月份, 返回一个 Month 枚举值
6getMonthValue() / getYear()获得月份(1-12) /获得年份
7getHours()/getMinute()/getSecond()获得当前对象对应的小时、分钟、秒
8withDayOfMonth()/withDayOfYear()/withMonth()/withYear()将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象
9with(TemporalAdjuster t)将当前日期时间设置为校对器指定的日期时间
10plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()向当前对象添加几天、几周、几个月、几年、几小时
11minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours()从当前对象减去几月、几周、几天、几年、几小时
12plus(TemporalAmount t)/minus(TemporalAmount t)添加或减少一个 Duration 或 Period
13isBefore()/isAfter()比较两个 LocalDate
14isLeapYear()判断是否是闰年(在LocalDate类中声明)
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class TestLocalDateTime {
    @Test
    public void test7(){
        LocalDate now = LocalDate.now();
        LocalDate before = now.minusDays(100);
        System.out.println(before);//2019-02-26
    }
    @Test
    public void test06(){
        LocalDate lai = LocalDate.of(2019, 5, 13);
        LocalDate go = lai.plusDays(160);
        System.out.println(go);//2019-10-20
    }
    @Test
    public void test05(){
        LocalDate lai = LocalDate.of(2019, 5, 13);
        System.out.println(lai.getDayOfYear());
    }
    @Test
    public void test04(){
        LocalDate lai = LocalDate.of(2019, 5, 13);
        System.out.println(lai);
    }
    @Test
    public void test03(){
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
    }
    @Test
    public void test02(){
        LocalTime now = LocalTime.now();
        System.out.println(now);
    }
    @Test
    public void test01(){
        LocalDate now = LocalDate.now();
        System.out.println(now);
    }
}

2、瞬时:Instant、ZondId和ZonedDateTime

常见时区ID:

Asia/Shanghai
UTC
America/New_York
America/Los_Angeles

可以通过ZondId获取所有可用的时区ID:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
public class TestZone {
    @Test
    public void test01() {
        //需要知道一些时区的id
        //Set<String>是一个集合,容器
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        //快捷模板iter
        for (String availableZoneId : availableZoneIds) {
            System.out.println(availableZoneId);
        }
    }
    @Test
    public void test02(){
        ZonedDateTime t1 = ZonedDateTime.now();
        System.out.println(t1);
        ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println(t2);
    }
    
    @Test
    public void test03(){
        Instant t = Instant.now();
        System.out.println(t);
    }
    
    @Test
    public void test4(){
        //以中国时区获取当前时间
        ZonedDateTime chinaNow = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        //将中国时间转换为美国纽约时间
        ZonedDateTime newYorkNow = chinaNow.withZoneSameInstant(ZoneId.of("America/New_York"));
        System.out.println("中国时区当前时间:" + chinaNow);
        System.out.println("将中国时间转换为美国纽约时间:"+newYorkNow);
    }
}

3、持续日期/时间:Period和Duration

Period:用于计算两个“日期”间隔

Duration:用于计算两个“时间”间隔

import org.junit.Test;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
public class TestPeriodDuration {
    @Test
    public void test01(){
        LocalDate t1 = LocalDate.now();
        LocalDate t2 = LocalDate.of(2018, 12, 31);
        Period between = Period.between(t1, t2);
        System.out.println(between);
        System.out.println("相差的年数:"+between.getYears());
        System.out.println("相差的月数:"+between.getMonths());
        System.out.println("相差的天数:"+between.getDays());
        System.out.println("相差的总数:"+between.toTotalMonths());
    }
    @Test
    public void test02(){
        LocalDateTime t1 = LocalDateTime.now();
        LocalDateTime t2 = LocalDateTime.of(2017, 8, 29, 0, 0, 0, 0);
        Duration between = Duration.between(t1, t2);
        System.out.println(between);
        System.out.println("相差的总天数:"+between.toDays());
        System.out.println("相差的总小时数:"+between.toHours());
        System.out.println("相差的总分钟数:"+between.toMinutes());
        System.out.println("相差的总秒数:"+between.getSeconds());
        System.out.println("相差的总毫秒数:"+between.toMillis());
        System.out.println("相差的总纳秒数:"+between.toNanos());
        System.out.println("不够一秒的纳秒数:"+between.getNano());
    }
}

4、日期时间格式化DateTimeFormatter

该类提供了三种格式化方法:

  • 预定义的标准格式。如:ISO_DATE_TIME;ISO_DATE
  • 本地化相关的格式。如:ofLocalizedDate(FormatStyle.MEDIUM)、ofLocalizedTime(FormatStyle.MEDIUM)、ofLocalizedDateTime(FormatStyle.MEDIUM)
  • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class TestDatetimeFormatter {
    @Test
    public void test1(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;//2019-06-06T16:38:23.756        String str = df.format(now);
        System.out.println(str);
    }
    
    @Test
    public void test2(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//2019年6月6日 下午04时40分03秒
        DateTimeFormatter df2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);//2019-6-6 16:40:37
        DateTimeFormatter df3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);//19-6-6 下午4:40
        DateTimeFormatter df4 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.systemDefault());//注意
        
        String str1 = df1.format(now);
        String str2 = df2.format(now);
        String str3 = df3.format(now);
        String str4 = df4.format(now);
        
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
        System.out.println(str4);
    }
    
    @Test
    public void test3(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 aHH点mm分ss秒SSS毫秒 E 是这一年的D天");
        String str = df.format(now);
        System.out.println(str);
    }
    
    @Test
    public void test4(){
        //String ==> LocalDateTime
        DateTimeFormatter dt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        String str = "2023年3月27日 下午07时26分43秒";
        LocalDateTime t = LocalDateTime.from(dt.parse(str));
        System.out.println(t);
    }
}

9.4.4 三代日期时间的转换

1、第一代与第二代

import org.junit.Test;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class TestDateTimeChange1 {
    @Test
    public void test1(){
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
        Date now = calendar.getTime();
        System.out.println(now);
    }
    @Test
    public void test2(){
        Date d = new Date();
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
        c.setTime(d);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DATE);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
    }
}

2、第一代与第三代

- Date与Instant - Date与LocalDateTime

package com.atguigu.review;
import org.junit.Test;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
public class TestDateTimeChange2 {
    @Test
    public void test1(){
        //Date ==> Instant
        Date d = new Date();
        Instant instant = d.toInstant();
        System.out.println(instant);
    }
    @Test
    public void test2(){
        //Instant ==> Date
        Instant instant = Instant.now();
        Date d = Date.from(instant);
        System.out.println(d);
    }
    @Test
    public void test3(){
        //Date ==> LocalDateTime
        Date d = new Date();
        LocalDateTime t = LocalDateTime.ofInstant(d.toInstant(), ZoneId.systemDefault());
        System.out.println(t);
    }
    
    @Test
    public void test4(){
        LocalDateTime now = LocalDateTime.now();//本地的日期时间对象
        Instant instant = now.toInstant(ZoneOffset.of("+08:00"));
        Date date = Date.from(instant);//第一代的Date
        System.out.println(date);
    }
    @Test
    public void test5(){
        //LocalDateTime ==> Date
        LocalDateTime now = LocalDateTime.now();//本地的日期时间对象
        ZonedDateTime zonedDateTime = now.atZone(ZoneId.systemDefault());//时区的日期时间对象
        Instant instant = zonedDateTime.toInstant();//瞬时对象
        Date date = Date.from(instant);//第一代的Date
        System.out.println(date);
    }
    
    
}