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

参考资料

posted @ 2016-04-16 18:00  20145107lcd  阅读(192)  评论(2编辑  收藏  举报