JavaEE - 09常用类2
(2)JDK8之前的日期时间API
- java.util.Date implements java.io.Serializable, Cloneable, Comparable<Date>
- java.sql.Date / java.sql.Time / java.sql.Timestamp
- java.util.Timezone implements Serializable, Cloneable
- java.util.Calendar implements Serializable, Cloneable, Comparable<Calendar>
- java.util.GregorianCalendar extends Calendar
- java.text.DateFormat extends Format
- java.text.SimpleDateFormat extends DateFormat
- java.text.NumberFormat extends Format
(2.1)java.lang.System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
计算世界时间的主要标准有:
- UTC(Coordinated Universal Time)
- GMT(Greenwich Mean Time)
- CST(Central Standard Time)
@Test public void test2(){ Long t1 = System.currentTimeMillis(); System.out.println(t1); //1606721150824 }
(2.2)java.util.Date类
表示特定的瞬间,精确到毫秒。
> 构造器
- Date(): 使用无参构造器创建的对象可以获取本地当前时间。
- Date(long date)
> 常用方法
- getTime(): 返回自1970年1月1日00:00:00 GMT以来此Date对象表示的毫秒数。
- toString(): 把Date对象转换成以下形式的String: dow mon dd hh:mm:ss zzz yyyy。 其中dow指一周中的某天,zzz是时间标准。
- 其他很多方法都已过时。
@Test public void test1(){ Date d1 = new Date(); // 构造器一:Date() System.out.println(d1.toString()); // Mon Nov 30 15:16:18 CST 2020 System.out.println(d1.getTime()); // 1606720578367 Date d2 = new Date(1606720363143L); // 构造器二 System.out.println(d2.toString()); // Mon Nov 30 15:12:43 CST 2020 // java.sql.Date 对应着数据库中的日期类型的变量,继承于 java.util.Date java.sql.Date d3 = new java.sql.Date(1606720363143L); System.out.println(d3); // 2020-11-30 Date d4 = new java.sql.Date(1606720363143L); // 2020-11-30 java.sql.Date d5 = (java.sql.Date) d4; // 2020-11-30 Date d6 = new Date(); java.sql.Date d7 = new java.sql.Date(d6.getTime()); // 2020-11-30 }
(2.3)java.text.SimpleDateFormat类
- Date类的API不易于国际化,大部分被废弃,java.text.SimpleDateFormat类是一个与语言环境无关的方式来格式化和解析日期的具体类。
- 它允许进行 格式化: 日期 -> 文本、解析: 文本 -> 日期
格式化:
- SimpleDateFormat(): 默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern): 该构造方法用参数pattern指定的格式创建一个对象
- public String format(Date date): 该方法格式化时间对象date
解析:
- public Date parse(String source): 从给定字符串的开始解析文本,以生成一个日期。
将字符串转换为java.util.Date类的对象(默认格式)
@Test public void test1() throws ParseException { // 实例化 SimpleDateFormat SimpleDateFormat sdf = new SimpleDateFormat(); // 格式化: 日期 --> 字符串 Date date = new Date(); System.out.println(date); //Mon Nov 30 16:04:46 CST 2020 String format = sdf.format(date); System.out.println(format); //20-11-30 下午4:04 // 解析: 字符串 --> 日期 String str = "20-10-05 下午3:43"; Date d1 = sdf.parse(str); System.out.println(d1); //M on Oct 05 15:43:00 CST 2020 }
将字符串转换为java.util.Date类的对象(自定义格式化)
@Test public void test2() throws ParseException { SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date date = new Date(); String format1 = sdf1.format(date); System.out.println(format1); // 2020-11-30 04:08:37 Date d2 = sdf1.parse("2019-11-08 13:33:42"); System.out.println(d2); // Fri Nov 08 13:33:42 CST 2019 }
将字符串转换为java.sql.Date类的对象
@Test public void test3() throws ParseException { String birth = "2020-09-09"; SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf1.parse(birth); System.out.println(date); // Wed Sep 09 00:00:00 CST 2020 java.sql.Date birthDate = new java.sql.Date(date.getTime()); System.out.println(birthDate); //2020-09-09 }
测试题: 从1990-01-01开始计算,三天打渔两天晒网,某天在干啥?
// 从1990-01-01开始计算,三天打渔两天晒网, 某天是干啥 @Test public void test4() throws ParseException { String startDay = "1990-01-01"; String date = "1990-01-01"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d1 = sdf.parse(startDay); Date d2 = sdf.parse(date); // 括号 int day = (int) ((d2.getTime() - d1.getTime()) / (1000*60*60*24)) + 1; String str = ""; switch (day % 5){ case 1: case 2: case 3: str = "今天打渔"; break; case 4: case 0: str = "今天晒网"; break; } System.out.println(str); }
(2.4)java.util.Calendar(日历)类
Calendar是一个抽象基类,用于完成日期字段之间相互操作的功能。 Object -> Calendar -> GregorianCalendar -> BuddhistCalendar
> 获取Calendar实例的方法
- 使用Calendar.getInstance()方法
- 调用它的子类GregorianCalendar的构造器
> 一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来获取想要的信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY、MINUTE、SECOND。获取月份时,一月是0,二月是1,...,12月是11; 获取星期时,周日是1,周一是2,...,周六是7
- public void set(int field, int value)
- public void add(int field, int amount)
- public final Date getTime()
- public final void setTime(Date date)
@Test public void test1(){ Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getClass()); // class java.util.GregorianCalendar int days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); // 30 int days2 = calendar.get(Calendar.DAY_OF_YEAR); System.out.println(days2); //335 // set() calendar.set(Calendar.DAY_OF_MONTH,22); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); // 22 System.out.println(calendar.getTime()); //Sun Nov 22 16:28:50 CST 2020 // add() calendar.add(Calendar.DAY_OF_MONTH,-3); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(calendar.getTime()); //Thu Nov 19 16:32:49 CST 2020 System.out.println(days); //19 // getTime() Date date = calendar.getTime(); System.out.println(date); //Thu Nov 19 16:32:49 CST 2020 // setTime() Date date1 = new Date(); calendar.setTime(date1); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); //30 }
(3)JDK8中新日期时间API
JDK1.0中包含了java.util.Date类,但是它大多数方法在JDK1.1引入Calendar类之后被弃用了。
而Calendar并不比Date好多少。面临的问题有:
- 可变性: 像日期和时间这样的类应该是不可变的。
- 偏移性: Date中的年份是从1900开始的,而月份是从0开始。
- 格式化: 格式化只对Date有用,Calendar则不行。
- 此外,它们也不是线程安全的;不能处理闰秒等。
@Test public void test3(){ Date d1 = new Date(2020,9,10); System.out.println(d1); // Sun Oct 10 00:00:00 CST 3920 Date d2 = new Date(2020 - 1900,9,10); // year 为偏移量 System.out.println(d2); // Sun Oct 10 00:00:00 CST 2020 }
Java8 吸收了Joda-Time的精华,引入了 java.time API,纠正了过去的缺陷。
java.time中包括了 本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。
Date类新增了toInstant()方法,用于把Date转换成新的表示形式。
- java.time 包含值对象的基础包
- java.time.chrono 提供对不同的日历系统的访问
- java.time.format 格式化和解析时间和日期
- java.time.temporal 包含底层框架和扩展特性
- java.time.zone 包含时区支持的类
(3.1)LocalDate、LocalTime、LocalDateTime
它们的实例是不可变的对象,分别表示使用ISO-8601日历系统(公历)的日期、时间、日期和时间。
它们提供了简单的本地日期或时间,但并不包含当前的时间信息,也不包含与时区相关的信息。
- LocalDate代表ISO格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期
- LocalTime代表一个时间,而不是日期。
- LocalDateTime表示时间和日期的。
方法 | 描述 |
now() / now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
of() | 静态方法,根据指定日期/时间创建对象 |
getDayOfMonth() / getDayOfYear() | 获取月份天数(1-31)/获得年份天数(1-366) |
getDayOfWeek() | 获取星期几(返回一个DayOfWeek枚举值) |
getMonth() | 获取月份,返回一个Month枚举值 |
getMonthValue() / getYear() | 获取月份(1-12)/获取年份 |
getHour()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
withDayOfMonth() / withDayOfYear() / withMonth() / withYear() | 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象 |
plusDays() / plusWeeks() / plusMonths() / plusYears() / plusHours() | 向当前对象添加几天、几周、几个月、几年、几小时 |
minusDays() / minusWeeks() / minusMonths() / minusYears() / minusHours() | 从当前对象减去几天、几周、几个月、几年、几小时 |
@Test public void test1(){ LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDate); //2020-11-30 System.out.println(localTime); //17:06:40.418 System.out.println(localDateTime); //2020-11-30T17:06:40.418 LocalDateTime ldt = LocalDateTime.of(2020,12,12,14,23,44); System.out.println(ldt); //2020-12-12T14:23:44 System.out.println(localDateTime.getDayOfYear()); //335 System.out.println(localDateTime.getDayOfMonth()); //30 System.out.println(localDateTime.getDayOfWeek()); //MONDAY System.out.println(localDateTime.getMonth()); //NOVEMBER System.out.println(localDateTime.getMonthValue()); //11 System.out.println(localDateTime.getYear()); //2020 // 体现不可变性 LocalDate localDate1 = localDate.withDayOfMonth(22); System.out.println(localDate); //2020-11-30 System.out.println(localDate1); //2020-11-22 LocalDateTime ldt3 = localDateTime.plusMonths(3); System.out.println(localDateTime); //2020-11-30T17:09:57.045 System.out.println(ldt3); //2021-02-28T17:09:57.045 LocalDateTime ldt4 = localDateTime.minusDays(7); System.out.println(localDateTime); //2020-11-30T17:09:57.045 System.out.println(ldt4); //2020-11-23T17:09:57.045 }
(3.2)瞬时: Instant
- Instant: 时间线上的一个瞬时点。可以被用来记录应用程序中的事件时间戳。
- 处理时间和日期时,年月日时分秒是面向人类的时间模型,通用模型是面向机器的。在UNIX中,从1970年开始,以秒为单位,Java中以毫秒为单位。
- java.time包通过值类型Instant提供机器视图。不需要任何上下文信息,如时区。表示从1970年1月1日00:00:00开始的秒数。精度可以达到纳秒级。
- 1秒 = 1000毫秒 = 10^6毫秒 = 10^9纳秒
方法 | 描述 |
now() | 静态方法,返回默认UTC时区的Instant类的对象 |
ofEpochMilli(long epochMilli) | 静态方法,返回在1970-01-01 00:00:00 基础上加上指定毫秒数之后的Instant类的对象 |
atOffSet(ZoneOffset offset) | 结合即时的偏移来创建一个 OffsetDateTime |
toEpochMilli() | 返回1970-01-01 00:00:00 到 当前时间的毫秒数,即为时间戳 |
时间戳是指格林威治时间1970-01-01 00:00:00(北京时间1970-01-01 08:00:00)起至现在的总秒数。
@Test public void test2(){ Instant instant = Instant.now(); System.out.println(instant); // 2020-11-30T09:26:13.897Z System.out.println(System.currentTimeMillis()); //1606728374034 // 添加时间的偏移量 OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); //2020-11-30T17:28:50.039+08:00 // 获取自1970-01-01 00:00:00(UTC)开始的毫秒数 long milli = instant.toEpochMilli(); System.out.println(milli); //1606728530039 // 通过给定的毫秒数,获取Instant对象 Instant instant1 = Instant.ofEpochMilli(1606728374034L); System.out.println(instant1); // 2020-11-30T09:26:14.034Z }
(3.3)格式化与解析日期、时间
java.time.format.DateTimeFormatter类: 提供了三种格式化方法
- 预定义的标准格式。如:ISO_LOCAL_DATE_TIME; ISO_LOCAL_DATE; ISO_LOCAL_TIME。
- 本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG/MEDIUM/SHORT)、ofLocalizedDate(FormatStyle.FULL/LONG/MEDIUM/SHORT)
- 自定义的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss E")
方法 | 描述 |
ofPattern(String pattern) | 静态方法,返回一个指定字符串格式的DateTimeFormatter |
format(TemporalAccessor t) | 格式化一个日期、时间,返回字符串 |
parse(Charequence text) | 将指定格式的字符序列解析为一个日期、时间 |
@Test public void test3(){ DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; // 预定义的标准格式。 LocalDateTime ldt = LocalDateTime.now(); String str = formatter.format(ldt); System.out.println(ldt); //2020-11-30T17:39:31.719 System.out.println(str); //2020-11-30T17:39:31.719 // 解析: 字符串 --> 日期 TemporalAccessor parse = formatter.parse("2020-02-18T17:40:12.897"); System.out.println(parse); //{},ISO resolved to 2020-02-18T17:40:12.897 // 本地化格式 DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); String str2 = formatter2.format(LocalDate.now()); System.out.println(str2); //2020年11月30日 星期一 // 自定义格式 ofPattern DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String str3 = formatter3.format(LocalDateTime.now()); System.out.println(str3); //2020-11-30 17:46:20 TemporalAccessor accessor = formatter3.parse("2020-09-08 17:09:07"); System.out.println(accessor); //{},ISO resolved to 2020-09-08T17:09:07 }
(3.4)其他API
- ZoneId: 该类中包含了所有的时区信息,一个时区的ID,如Europe/Paris
- ZonedDateTime: 一个在ISO-8601日历系统时区的日期时间,如 2007-12-12T10:09:08+01:00 Europe/Paris。
- 其中每个时区都对应着ID,地区ID都为"{区域}/{城市}"的格式,如:Asia/Shanghai等
- Clock: 使用时区提供对当前即时、日期和时间的访问的时钟。
- Duration:持续时间,用于计算两个"时间"间隔。
- Period: 日期间隔,用于计算两个"日期"间隔。
- TemporalAdjuster: 时间校正器。如:将日期调整到"下一个工作日"等操作。
- TemporalAdjusters: 该类通过静态方法firstDayOfXxx()/lastDayOfXxx()/nextXxx() 提供了常用TemporalAdjuster的实现。
(3.5)参考:与传统日期处理的转换
类 | To 遗留类 | From 遗留类 |
java.time.Instant 与 java.util.Date | Date.from(instant) | date.toInstant() |
java.time.Instant 与 java.sql.Timestamp | Timestamp.from(instant) | timestamp.toInstant() |
java.time.ZonedDateTime与java.util.GregorianCalendar | GregorianCalendar.from(zonedDateTime) | cal.toZonedDateTime() |
java.time.LocalDate 与 java.sql.Time | Date.valueOf(localDate) | date.toLocalDate() |
java.time.LocalTime 与 java.sql.Time | Date.valueOf(localDate) | date.toLocalTime() |
java.time.LocalDateTime 与 java.sql.Timestamp | Timestamp.valueOf(localDateTime) | timestamp.toLocalDateTime() |
java.time.ZoneId与java.util.TimeZone | Timezone.getTimeZone(id) | timeZone.toZoneId() |
java.time.format.DateTimeFormatter与java.text.DateFormat | formatter.toFormat() | 无 |