20145107 《Java程序设计》第七周学习总结
20145107 《Java程序设计》第七周学习总结
教材学习内容总结
在本周,我们进行了第十二,十三章的学习,本周的学习目标是:
了解Lambda语法
了解方法引用
了解Fucntional与Stream API
掌握Date与Calendar的应用
会使用JDK8新的时间API
因为Lambda语法在前面的第九章里学过一些基本的内容,对Lambda语法也有了初步的了解,所以,在本周的学习重点放在了第十三章:时间与日期上。
第十三章: 时间和日期
- 时间与日期简史
时间是个很复杂的问题,用程序来设计时间也并不是像我们像想的那样简单。在正式学习Java中有关时间处理的API之前,书中先是介绍了一些有关时间的历史问题,这样对我们在后面对于时间类API的应用很有帮助。
想要度量时间有很多基准,我们最熟悉的应该就是格林尼治时间,它一开始是参照英国皇家格林尼治天文台的标准太阳时间,其标准是正午太阳抵达天空的最高点的时候。然而由于地球的公转轨道为椭圆形而且速度并不唯一,地球本身的自转也有一定的时间误差,所以格林尼治时间(GMT)已经不作为标准时间进行使用了。
另一个便是“世界时”(UT),它是由观测远方星体跨国子午线而得的。在1935年便建议用更精确的UT来代替GMT,在1972年引进UTC之前,两者其实是相同的。
后来人们发现,即便是使用UTC还是会受到地球自转的影响而产生误差。所以,在1967年国际原子时将妙偶的国际单位定义为铯原子的辐射振动9192631770周耗费的时间,时间从1958年开始与UT同步。
再后来还有世界协调时间,UNIX时间,epoch时间等。
想要学习本章的知识还要求对日历的标准,计算,时区的标准,计算有一定的掌握。这样会更方便本章的学习。书中已经有了详细的介绍,对我们很有帮助。 - 13.2:Date与Calender:
时间轴上瞬间的Date:
我们要是想要取得系统时间,方法之一就是使用System.currentTimeMillis
,返回的是long型的整数,代表的是1970年1月1日0时0分0毫秒至今经过的毫秒数,也就是与之前UNIX的时间计量方法相似,估计苹果的时间计量方法也差不多,要不然不会出现时间设置在1970年之前就会变砖的情况。这种方法取得的是机器的时间观点代表着时间轴上的某一个瞬间,我们可以取得Date实例来取得系统时间的描述,虽然Date也是偏向机器的时间观点。Date的代码如下:
package DateCalendar;
import java.util.*;
import static java.lang.System.*;
public class DateDemo {
public static void main(String[] args) {
Date date1 = new Date(currentTimeMillis());
Date date2 = new Date();
out.println(date1.getTime());
out.println(date2.getTime());
}
}
程序在IDEA上的运行结果如下:
程序运行结果显示的数字也就是1970年1月1日至今所经过的毫秒数。
格式化时间日期的DateFormat:
有关字符串时间格式的处理,其职责落到了java.text.Dateformat
身上。Dateformat是一个抽象类,其操作类是java.text.SimpleDateFormat
,下面这个程序向我们展示了如何通过DateFormat的各种静态方法进行格式化的:
package DateCalendar;
import java.util.*;
import static java.lang.System.out;
import static java.text.DateFormat.*;
public class DateFormatDemo {
public static void main(String[] args) {
Date date = new Date();
dateInstanceDemo(date);
timeInstanceDemo(date);
dateTimeInstanceDemo(date);
}
static void dateInstanceDemo(Date date) {
out.println("getDateInstance() demo");
out.printf("\tSHORT: %s%n", getDateInstance(LONG).format(date));
out.printf("\tSHORT: %s%n", getDateInstance(SHORT).format(date));
}
static void timeInstanceDemo(Date date) {
out.println("getTimeInstance() demo");
out.printf("\tLONG: %s%n", getTimeInstance(LONG).format(date));
out.printf("\tMEDIUM: %s%n", getTimeInstance(MEDIUM).format(date));
out.printf("\tSHORT: %s%n",getTimeInstance(SHORT).format(date));
}
static void dateTimeInstanceDemo(Date date) {
out.println("getDateTimeInstance() demo");
out.printf("\tLONG: %s%n",
getDateTimeInstance(LONG, LONG).format(date));
out.printf("\tMEDIUM: %s%n",
getDateTimeInstance(SHORT, MEDIUM).format(date));
out.printf("\tSHORT: %s%n",
getDateTimeInstance(SHORT, SHORT).format(date));
}
}
程序运行的结果如下所示:
上面的不同方法是取到了不同详细程度的时间日期。其实,我们也可以直接构建SimpleDateFormat,这样我们就可以使用模式字符串自定义格式。它还有一个prase()方法,可以构建SimpleDateFormat时指定的格式,将指定的字符串剖析为Date实例:
package DateCalendar;
import java.util.*;
import java.text.*;
public class HowOld {
public static void main(String[] args) throws Exception {
System.out.print("输入出生年月日(yyyy-mm-dd):");
DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
Date birthDate = dateFormat.parse(new Scanner(System.in).nextLine());
Date currentDate = new Date();
long life = currentDate.getTime() - birthDate.getTime();
System.out.println("你今年的年龄为:" +
(life / (365 * 24 * 60 * 60 * 1000L)));
}
}
程序运行的结果如下:
处理时间日期的Calendar:
在时间的处理中,若是我们想取得某个时间信息或者对时间信息进行操作,我们可以用Caendar实例。它是一个混合类,操作了儒略历与格里高利历的混合历,在书中,若是我们想比较两个Calendar的日期先后,可以使用after和before的方法。在这里使用Calendar计算用户的岁数才是比较合理的。
package DateCalendar;
import static java.lang.System.out;
import java.util.Calendar;
public class CalendarUtil {
public static void main(String[] args) {
Calendar birth = Calendar.getInstance();
birth.set(1996, Calendar.AUGUST, 27);
Calendar now = Calendar.getInstance();
out.printf("岁数:%d%n", yearsBetween(birth, now));
out.printf("天数:%d%n", daysBetween(birth, now));
}
public static long yearsBetween(Calendar begin, Calendar end) {
Calendar calendar = (Calendar) begin.clone();
long years = 0;
while (calendar.before(end)) {
calendar.add(Calendar.YEAR, 1);
years++;
}
return years - 1;
}
public static long daysBetween(Calendar begin, Calendar end) {
Calendar calendar = (Calendar) begin.clone();
long days = 0;
while (calendar.before(end)) {
calendar.add(Calendar.DATE, 1);
days++;
}
return days - 1;
}
}
程序运行如下:
设定TimeZone
在前面使用Calendar时并没有使用时区信息,在这里,我们可以使用java.util.TimeZone
的```getDefault()来取得默认时区信息。
书中有如下代码:
package DateCalendar;
import static java.lang.System.out;
import java.util.TimeZone;
public class TimeZoneDemo {
public static void main(String[] args) {
TimeZone timeZone = TimeZone.getDefault();
out.println(timeZone.getDisplayName());
out.println("\t时区ID:" + timeZone.getID());
out.println("\t日光节约时数:" + timeZone.getDSTSavings());
out.println("\tUTC 偏移毫秒数:" + timeZone.getRawOffset());
}
}
程序运行截图如下:
Calendar在调用getInstance()时,可以指定TimeZone,如果已经取得Calendar实例,也可以通过setTimeZone()方法设定TimeZone,示例如下:
package DateCalendar;
import java.util.*;
import static java.lang.System.out;
public class TimeZoneDemo2 {
public static void main(String[] args) {
TimeZone taipeiTz = TimeZone.getTimeZone("Asia/Taipei");
Calendar calendar = Calendar.getInstance(taipeiTz);
showTime(calendar);
TimeZone copenhagenTz = TimeZone.getTimeZone("Europe/Copenhagen");
calendar.setTimeZone(copenhagenTz);
showTime(calendar);
}
static void showTime(Calendar calendar) {
out.print(calendar.getTimeZone().getDisplayName());;
out.printf(" %d:%d%n",
calendar.get(Calendar.HOUR),
calendar.get(Calendar.MINUTE));
}
}
程序运行截图如下:
- 13.3JDK新时间日期API
人类时间观点API:
如果我们的时间需要带有时区,可以基于LocalDateTime,LocalDate,LocalTime
来弥补缺少的信息:
package DateCalendar;
import static java.lang.System.out;
import java.time.*;
public class ZonedDataTimeDemo {
public static void main(String[] args) {
LocalTime localTime = LocalTime.of(0, 0, 0);
LocalDate localDate = LocalDate.of(1975, 4, 1);
ZonedDateTime zonedDateTime = ZonedDateTime.of(
localDate, localTime, ZoneId.of("Asia/Taipei"));
out.println(zonedDateTime);
out.println(zonedDateTime.toEpochSecond());
out.println(zonedDateTime.toInstant().toEpochMilli());
}
}
程序运行如下:
year,month,yearmonth与monthday:
如果我们只想表示2014年,可以使用year,如果想表示2014/5可以使用yearmonth。如果只想表示五月,可以使用month,如果想表示5/4,可以使用monthday,其中months是emnu型。如果你想去的代表月份的数字,不要使用oridinal()方法从0开始,想要取得代表月份的数要通过getvalue()方法。,书中有程序示例如下:
package DateCalendar;
import static java.lang.System.out;
import java.time.Month;
public class MonthDemo {
public static void main(String[] args) {
for(Month month : Month.values()) {
out.printf("original: %d\tvalue: %d\t%s%n",
month.ordinal(), month.getValue(), month);
}
}
}
程序的执行情况如下所示:
对时间的运算:
在JDK8中,新日期时间处理实现了流畅API的概念,这是一种计算时间的新的方法,我们在前面曾经写过HowOld.java,在这里我们可以使用新方法进行改进,修改后的程序如下:
package DateCalendar;
import java.time.*;
import java.util.Scanner;
import static java.lang.System.out;
public class HowOld2 {
public static void main(String[] args) {
out.print("输入出生年月日(yyyy-mm-dd):");
LocalDate birth = LocalDate.parse(new Scanner(System.in).nextLine());
LocalDate now = LocalDate.now();
Period period = Period.between(birth, now);
out.printf("你活了 %d 年 %d 月 %d 日%n",
period.getYears(), period.getMonths(), period.getDays());
}
}
程序执行情况如下:
教材学习中的问题和解决过程
在本章的代码编译中,一定要注意日期书写的规范,在上面的HowOld2.java程序中我在程序里输入自己的信息,但却编译不出来,后来一看原来是输入的数据不规范,8应该写成08,这样才会有结果,否则就像下面一样:
本周代码链接:
本周代码托管截图
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 100/300 | 1/3 | 18/38 | |
第三周 | 200/500 | 1/4 | 22/60 | |
第四周 | 250/750 | 1/5 | 30/90 | |
第五周 | 450/1200 | 1/6 | 20/110 | |
第六周 | 400/1600 | 2/8 | 30/140 | |
第七周 | 150/1750 | 2/10 | 30/170 |