Java处理日期、日历和时间的方式一直被人所诟病,将 java.util.Date设定为可变类型,以及SimpleDateFormat的非线程安全使其应用非常受限。

新API基于ISO标准日历系统,java.time包下的所有类都是不可变类型而且线程安全。

(因为更安全,不可变了,所以就需要每一个日期搞一个变量(实例?)

18 个 Java8 日期处理的实践,太有用了!

Instant 时间戳
Duration 持续时间,时间差
LocalDate 只包含日期,比如:2018-02-05
LocalTime 只包含时间,比如:23:12:10
LocalDateTime 包含日期和时间,比如:2018-02-05 23:14:21
Period 时间段
ZoneOffset 时区偏移量,比如:+8:00
ZonedDateTime 带时区的时间
Clock 时钟,比如获取目前美国纽约的时间
java.time.format.DateTimeFormatter 时间格式化

示例1:Java 8中获取今天的日期

Java 8 中的 LocalDate 用于表示当天日期。和java.util.Date不同,它只有日期,不包含时间。当你仅需要表示日期时就用这个类。

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{ 
        LocalDate today = LocalDate.now();
        System.out.println("today is:"+today);
  
    }
}
//output:
//today is:2020-02-29

而如果需要将年月日信息分开:那么我们可以利用上面的today继续操作;

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{ 
        LocalDate today = LocalDate.now();
        System.out.println("today is:"+today);
        int year = today.getYear();
        int month = today.getMonthValue();
        int day = today.getDayOfMonth();
        System.out.println(""+year+month+day);
    }
}

注意:其中还有getMonth(),返回的是一个枚举month里的值(是“FEBRUARY”这种)

而getMonthValue()则返回一个值(2)所以我们还能发现许多这样的用法,比如day_of_year()等

示例2:自定义日期:

我们通过静态工厂方法now()非常容易地创建了当天的日期,我们还可以调用另一个有用的工厂方法LocalDate.of()创建任意日期, 该方法需要传入年、月、日做参数,返回对应的LocalDate实例。这个方法的好处是没再犯老API的设计错误(而且我们也可以使用localDate的方法了),比如年度起始于1900,月份是从0开 始等等(这些问题就不提了哎,文末可能会吐槽一下,并演示一下有多么讨厌)。

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{ 
        LocalDate fakeDate = LocalDate.of(2020,2,28);
        System.out.println("yesterday is:"+fakeDate);
        
   }
}
//output:
//yesterday is:2020-02-28

示例三:判断两个日期是否相同使用.equals()

示例四:检查像生日这种周期性事件:MonthDay:

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{   LocalDate date1 = LocalDate.now();
        LocalDate date = LocalDate.of(2020,2,28);
        MonthDay birthday = MonthDay.of(date.getMonthValue(),date.getDayOfMonth());
        MonthDay nowMonthDay = MonthDay.now();
        if(nowMonthDay.equals(birthday))
        System.out.println("yes");
        else System.out.println("nonono");
    }
}
//output:
//nonono

注意在这里getMonthValue()和getMonth()都是可以使用的。

说完日期,说说时间:

示例五:获取当前时间

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        LocalTime now = LocalTime.now();
        System.out.println(now);
    }
}
//output:
19:27:01.708

这个时间的精度。。可以了

示例六:计算一段时间前/后的时间.plus(val,ChronoUnit.WEEKS)

/.minus(val,ChronoUnit.WEEKS))

import java.time.*;
import java.time.temporal.ChronoUnit;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        LocalDate now = LocalDate.now();
        LocalDate after = now.plus(1,ChronoUnit.WEEKS);

        System.out.println(after);
    }
}

这里是日期,那么就要用localDate了

示例七:Java 8的Clock时钟类

Java 8增加了一个Clock时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。以前用到System.currentTimeInMillis()和TimeZone.getDefault()的地方都可用Clock替换

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        Clock clock = Clock.systemUTC();
        System.out.println("Clock : " + clock.instant());
        System.out.println("Clock : " + clock.millis());
        // Returns time based on system clock zone
        Clock defaultClock = Clock.systemDefaultZone();
        System.out.println("Clock : " + defaultClock.millis());

    }
}
//output:
//Clock : 2020-03-01T03:06:27.520Z
//Clock : 1583031987647
//Clock : 1583031987687

示例八:如何用Java判断日期是早于还是晚于另一个日期

另一个工作中常见的操作就是如何判断给定的一个日期是大于某天还是小于某天?在Java 8中,LocalDate类有两类方法isBefore()和isAfter()用于比较日期。调用isBefore()方法时,如果给定日期小于当前日期则返回true。当然也可判断是否日期相同。

import java.time.*;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        LocalDate today = LocalDate.now();
        LocalDate fakeDate = LocalDate.of(2019, 2, 1);
        if(fakeDate.isBefore(today))
        {
            System.out.print("yes");
        }
        else System.out.print("nono");

    }
}
//output:
//yes

示例九:Java 8中处理时区

Java 8不仅分离了日期和时间,也把时区分离出来了。现在有一系列单独的类如ZoneId来处理特定时区,ZoneDateTime类来表示某时区下的时间。这在Java 8以前都是 GregorianCalendar类来做的。下面这个例子展示了如何把本时区的时间转换成另一个时区的时间。

其他:同样也可以检查闰年,独立的年月计算两个日期之间天数(between)

示例十:Java 8中如何使用预定义的格式化工具去解析或格式化日期

import java.time.*;
import java.time.format.DateTimeFormatter;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        String dayAfterTommorrow = "20200302";
        LocalDate formatted = LocalDate.parse(dayAfterTommorrow,DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(dayAfterTommorrow+"  格式化后的日期为:  "+formatted);
    }
}
//output:
//20200302  格式化后的日期为:  2020-03-02

示例十一:字符串互转日期类型

import java.time.*;
import java.time.format.DateTimeFormatter;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        LocalDateTime date = LocalDateTime.now();

        DateTimeFormatter format1 = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm:ss");
    //日期转字符串
        String str = date.format(format1);

        System.out.println("日期转换为字符串:"+str);

        DateTimeFormatter format2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    //字符串转日期
        LocalDate date2 = LocalDate.parse(str,format2);
        System.out.println("日期类型:"+date2);


    }
}
//output:
//日期转换为字符串:2020/03/01 11:44:03
//日期类型:2020-03-01

如果我们将str的内容更换一下,只要format的内容一致:

import java.time.*;
import java.time.format.DateTimeFormatter;
class dealWithTime
{ 
	public static void main (String[] args) 
	{
        String str = "20190112120101";

        DateTimeFormatter format2 = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    //字符串转日期
        LocalDate date2 = LocalDate.parse(str,format2);
        System.out.println("日期类型:"+date2);


    }
}
//output:
//日期类型:2019-01-12

在这其中我们还是有很多可以去挖掘的。。。

对了,最后吐槽一下

class dealWithTime
{ 
	public static void main (String[] args) 
	{
        
        long t = System.currentTimeMillis();

        System.out.println(t);


    }
}

这玩意返回的必须是long类型但是把现在也用不到。返回的时间是距离1970年一月一日零点零分的毫秒数。。