Java类库中的LocalDate类
Date类的实例有一个状态,即特定的时间点
时间是用距离一个固定时间点的毫秒数(可正可负)表示的,这个时间点就是纪元,它是UTC时间1970年1月1日00:00:00。
UTC就是Coordinated Universal Time(国际协调时间),和GMT(Greenwich Mean Time,格林尼治时间)一样,都是科学标准时间。
但是Date类对于处理人类记录日期的日历信息并不是很有用,如"December 31, 1999"。这种特定的日期描述遵循了世界上大多数地区使用的Gregorian阳历。
但是同样的这个时间点采用中国或希伯来的阴历来描述就不一样了。
类库设计者决定将保存时间与给时间点命名分开。所以标准Java类库分别包含了两个类:一个是用来表示时间点的Date类;另一个是用大家熟悉的日历表示法表示日期的LocalDate类。
将时间度量与日历分开是一种很好的面向对象设计。所以,最好使用不同的类表示不同的概念。
- 不要使用构造器来构造LocalDate类的对象。实际上,应该使用静态工厂方法,它会代表你调用构造器。
LocalDate.now()
会构造一个新对象,表示构造这个对象时的日期。
LocalDate.of(1999, 12, 31)
可以提供年、月、日来构造对应一个特定日期的对象。
LocalDate newYearsEve = LocalDate.of(1999, 12, 31);
将构造的对象保存在一个对象变量中。
// 一旦有一个LocalDate对象,可以用方法getYear、getMonthValue和getDayOfMonth得到年、月、日
int year = newYearsEve.getYear(); // 1999
int month = newYearsEve.getMonthValue(); // 12
int day = newYearsEve.getDayOfMonth(); // 31
plusDays
方法会得到一个新的LocalDate,如果把应用这个方法的对象称为当前对象,这个新日期对象就是距离当前对象指定天数的一个新日期
plusDays
方法会生成一个新的LocalDate对象,然后把新对象赋给aThousandDaysLater变量。原来的对象不做任何改动。所以plusDays
方法没有 更改 这个方法的对象。
只访问对象而不修改对象的方法被称为访问器方法。例如,LocalDate.getYear
LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);
year = aThousandDaysLater.getYear(); // 2002
month = aThousandDaysLater.getMonthValue(); // 09
day = aThousandDaysLater.getDayOfMonth(); // 26
LocalDate类封装了实例字段来维护所设置的日期。如果不查看源代码,就不知道类内部的日期表示。封装的意义就在于内部表示并不重要,重要的是类对外提供的方法。
Date类也有得到年、月、日的方法,分别是getDay、getMonth、getYear,不过这些方法已经废弃。(当类库设计者意识到某个方法最初就不该引入的时候,就把它标记为废弃,不鼓励使用。虽然程序中可以使用这些方法,但是不推荐使用,因为可能在未来的版本中完全删除它们)
JDK提供了jdeprscan工具来检查你代码中是否使用了Java API已经废弃的特性。
打印日历
package time;
import java.time.DayOfWeek;
import java.time.LocalDate;
public class CalendarTest {
public static void main(String [] args){
// 首先构造一个对象,并用当前的日期初始化
LocalDate date = LocalDate.now();
// 获得当前的月份和日期
int month = date.getMonthValue();
int today = date.getDayOfMonth();
// 将date设置为这个月的第一天,并得到这一天为星期几
date = date.minusDays(today - 1); // set to start of month
// 得到星期几的一个数值,国际惯例,周末是一周的末尾
DayOfWeek weekday = date.getDayOfWeek();
int value = weekday.getValue(); // 1 = Monday, ... , 7 = Sunday
// 日历第一行是缩进的,使月份的第一天指向相应的星期几
System.out.println("Mon Tue Wed Thu Fri Sat Sun");
// 打印日历主体,到达新的一周的第一天换行
for (int i = 1; i < value; i++){
System.out.print(" ");
}
while (date.getMonthValue() == month){
System.out.printf("%3d", date.getDayOfMonth());
if (date.getDayOfMonth() == today){
System.out.printf("*");
}else{
System.out.printf(" ");
}
date = date.plusDays(1);
if (date.getDayOfWeek().getValue() == 1){
System.out.println();
}
}
if (date.getDayOfWeek().getValue() != 1){
System.out.println();
}
}
}