Java日期时间主要API:java.time.chrono.Chronology接口及其实现类IsoChronology

本文所有源码的jdk版本是:jdk-13.0.1

Chronology接口代表日历系统接口,实现这个接口的类表示某一个日历系统。

Chronology接口的官方文档:https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/time/chrono/Chronology.html

世界上有很多不同的日历系统。其中我们日常使用的公历属于ISO日历系统,这个是世界通用的标准日历系统。除此之外还有非通用的,比如日本历、泰国日历、中华民国日历、伊斯兰历、农历等。

java已经写好了一些类代表一些常用的日历系统:

Java日期时间主要API:java.time.chrono.Chronology接口及其实现类IsoChronology_第1张图片

其中IsoChronology类就是代表ISO日历系统。HijrahChronology是伊斯兰日历系统,JapaneseChronology是日本历,MinguoChronology是民国历,ThaiBuddhistChronology是泰国佛教历。除了ISO日历系统,其他日历系统我们都不怎么用,因此不作介绍。而java的日期依赖的就是ISO日历系统。

1.1  IsoChronology类的属性

这里介绍其中一个静态属性:

    /**
     * Singleton instance of the ISO chronology.
     */
    public static final IsoChronology INSTANCE = new IsoChronology();

这里用了单例设计模式,因为日历系统只需要一个就够了。这个类的构造方法是私有的,所以获取ISO日历系统实例的方法只有:

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
	}

1.2  IsoChronology类的方法

获取IsoChronology类所代表的日历系统的ID和类型

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		System.out.println(iso.getId());//ISO
		System.out.println(iso.getCalendarType());//iso8601
	}

 用日历系统创建本地LocalDate日期对象,传入时代对象、年、月、日

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		LocalDate ld1=iso.date(1,1,1);
		System.out.println(ld1);// 0001-01-01
		//公历公元1年为0001年,以公元前1年为0000年,公元前2年为-0001年,其他以此类推。
		//A definition has therefore been created with two eras 
		//'Current era' (CE) for years on or after 0001-01-01 (ISO)
		//and 'Before current era' (BCE) for years before that.
		LocalDate ld2=iso.date(IsoEra.BCE,10,10,10);
		System.out.println(ld2);// -0009-10-10
		LocalDate ld3=iso.date(IsoEra.CE,10,10,10);
		System.out.println(ld3);// 0010-10-10
	}

不同的日历系统有不同的时代划分,比如公历有两个:公元(CE)和公元前(BCE);而日本历则每一个天皇都可能有一个时代,比如明治时代、昭和时代等。关于上述几个日历系统的时代java已经帮我们枚举出来了,有空大家可以查看一下源码:

Java日期时间主要API:java.time.chrono.Chronology接口及其实现类IsoChronology_第2张图片

Era接口的官方文档:https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/time/chrono/Era.html 

根据时代对象、年、天数来创建本地LocalDate对象。天数必须要传1~365/366之间的整数,否则报错。

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		LocalDate ld1=iso.dateYearDay(2, 100);
		System.out.println(ld1);// 0002-04-10
		LocalDate ld2=iso.dateYearDay(IsoEra.CE, 2, 100);
		System.out.println(ld2);
		LocalDate ld3=iso.dateYearDay(IsoEra.BCE, 2, 100);
		System.out.println(ld3);// -0001-04-10
	}

dateEpochDay(long)方法从纪元天开始按传入的天数获取本地日期。纪元天指1970-01-01

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		LocalDate ld1=iso.dateEpochDay(0);
		System.out.println(ld1);// 1970-01-01
		LocalDate ld2=iso.dateEpochDay(10);
		System.out.println(ld2);// 1970-01-11
	}

从另一个日期时间对象获取ISO当地日期。和LocalDate.from(TemporalAccessor)等价

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		LocalDate ld1=iso.date(LocalDate.of(1, 1, 1));
		System.out.println(ld1);// 0001-01-01
	}

从 1970-01-01T00:00:00Z 的UTC时间开始获取到指定的日期时间的秒数。可以为负数。ZoneOffset对象指与格林威治/ UTC的时区偏移量,北京时间是东八区时间,时区偏移量是+0800(比UTC时间快8小时)。

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		long seconds=iso.epochSecond(2019, 12, 16, 20, 48, 30, ZoneOffset.of("+0800"));
		System.out.println(seconds);// 1576500510
		long seconds2=iso.epochSecond(IsoEra.CE, 1960, 12, 16, 20, 48, 30, ZoneOffset.of("+0800"));
		System.out.println(seconds2);// -285333090
	}

关于ZoneOffset类的详细介绍请移步我的另一篇博文>>>Java日期时间主要API:java.time.ZoneId及其子类ZoneOffset

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		//LocalDateTime是本地时间,和操作系统时间同步,不带有时区信息
		//ZoneDateTime也是本地时间,但是带有时区信息。
                //从另一个时间对象获取此时间顺序中的本地日期时间(简直就是复制)
		LocalDateTime ldt=iso.localDateTime(LocalDateTime.of(2019, 12, 12, 12, 12,12));
		System.out.println(ldt);// 2019-12-12T12:12:12
                //和上面一样。
		ZonedDateTime zdt1=iso.zonedDateTime(ZonedDateTime.now());
		System.out.println(zdt1);// 2019-12-16T21:22:18.583088800+08:00[Asia/Shanghai]
                //根据时间瞬时点和该瞬时点的时区来创建一个日期时间对象
		ZonedDateTime zdt2=iso.zonedDateTime(Instant.now(),ZoneId.of("America/New_York"));
		System.out.println(zdt2);// 2019-12-16T21:22:18.583088800-05:00[America/New_York]
	}

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		//当前日期
		LocalDate ld1=iso.dateNow();
		System.out.println(ld1);//2019-12-16
		//现在北京时间是12月16日22时,而太平洋/奥克兰时区的日期已经是12月17日了
		LocalDate ld2=iso.dateNow(ZoneId.of("Pacific/Auckland"));
		System.out.println(ld2);//2019-12-17
		//Clock可以理解为就是一个时钟,有日期时间等信息,通过某些方法获取这些信息
                //Clock.systemUTC()获取当下零时区的时钟,根据时钟的日期信息创建一个日期对象。
		LocalDate ld3=iso.dateNow(Clock.systemUTC());
		System.out.println(ld3);//2019-12-16
	}	

关于Clock类的详细介绍请移步我的另一篇博文>>>Java日期时间主要API:java.time.Clock抽象类及其子类

isLeapYear(long)查看给定的年份是否为闰年

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		System.out.println(iso.isLeapYear(2004)); //true
	}

prolepticYear(Era, int)给定一个Era对象和一个int类型数值,看看这个数值在这个时代中代表多少年。

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		//公元前2003年
		System.out.println(iso.prolepticYear(IsoEra.BCE, 2004)); //-2003
	}

eraOf(int)根据数字值创建年代时代对象。从概念上讲,该时代是时间线的最大划分。大多数日历系统只有一个纪元,将时间线分为两个时代。但是,有些有多个时代,例如每个领导人的统治时期。确切的含义由时间顺序根据以下约束条件确定:1970年1月1日使用的时代必须具有值1。以后的时代必须具有依次更高的值。较早的时代必须具有依次较低的值。每个日历系统必须引用一个枚举或类似的单例来提供时代值。

在ISO日历系统中,java已经用一个枚举类IsoEra为我们枚举了两个时代值:BCE(公元前,值为0)和CE(公元,值为1)。

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		//公元前
		System.out.println(iso.eraOf(0)); //BCE
		//公元
		System.out.println(iso.eraOf(1)); //CE
	}

eras()方法返回这个日历系统的所有时代的list集合

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		//ISO日历系统的所有时代集合
		System.out.println(iso.eras()); //[BCE, CE]
		JapaneseChronology japan=JapaneseChronology.INSTANCE;
		//日本历所有时代集合
		System.out.println(japan.eras());//[Meiji, Taisho, Showa, Heisei, Reiwa]
	}

resolveDate(Map, ResolverStyle)方法留给大家探讨

range(ChronoField)查看这个日历系统的一些日期时间字段的数值范围

	public static void main(String[] args) {
		IsoChronology iso=IsoChronology.INSTANCE;
		//ISO日历系统中每月的天数这个字段的数值范围是多少(每月最小值是1,最大值在28~31天之间)
		System.out.println(iso.range(ChronoField.DAY_OF_MONTH)); //1 - 28/31
	}

ChronoField是日期时间字段的枚举类。关于ChronoField类的详细介绍请移步我的另一篇博文>>>Java日期时间主要API:java.time.temporal.TemporalField接口及其实现类ChronoField

period(int, int, int)这个方法与Period.of(int years, int months, int days)这个方法等价

谢谢浏览!

你可能感兴趣的:(Java)