Java中时间处理

旧 API:位于 java.util 包中,里面主要有 Date、Calendar、TimeZone 类 新 API:位于 java.time 包中,里面主要有 LocalDateTime、ZonedDateTime、ZoneId 类

Date

public static void main( String[] args )
{
	Date date = new Date();
	System.out.println(date.getYear()+1900);  // 2020
	System.out.println(date.getMonth()+1);  // 0~11
	System.out.println(date.getDate());  // 9
	System.out.println(date.toString());  // Mon Mar 09 15:33:13 CST 2020
	System.out.println(date.toLocaleString());  // 2020-3-9 15:33:13
	System.out.println(date.toGMTString());  // 9 Mar 2020 07:33:13 GMT
}

年从1900开始算;月分从0开始算,所以需要加1

缺点:

  1. 无法设置时区
  2. 无法加减日期
  3. 无法计算某天是星期几

eclipse在jdk1.8下,这些函数基本都带中划线,不建议使用了

SimpleDateFormat

为了能设置时区,有了SimpleDateFormat类

public static void main( String[] args )
{
	Date date = new Date();
	SimpleDateFormat formatter = new SimpleDateFormat("y-M-d H:m:s");  // 2020-3-9 15:48:6
	System.out.println(formatter.format(date));
	formatter.setTimeZone(TimeZone.getTimeZone("GMT-8:00"));  // 2020-3-8 23:48:6
	System.out.println(formatter.format(date));
}

常用的格式化字符串: y:年 M:月 d:日 H:小时 m:分钟 s:秒 S:毫秒 a:上午 / 下午 E:星期 z:时区

Calendar

为了加减日期,有了Calendar类

public static void main( String[] args )
{
	Calendar c = Calendar.getInstance();
	//c.set(Calendar.DAY_OF_WEEK, 1);  // 这里设置后时间会自动变为当周日的年月日
	int y = c.get(Calendar.YEAR);  // 不比加1900
	int M = c.get(Calendar.MONDAY) + 1;  // 仍然用0~11表示1~12月份
	int d = c.get(Calendar.DAY_OF_MONTH);
	int H = c.get(Calendar.HOUR_OF_DAY);
	int m = c.get(Calendar.MINUTE);
	int s = c.get(Calendar.SECOND);
	int S = c.get(Calendar.MILLISECOND);
	int E = c.get(Calendar.DAY_OF_WEEK);
	System.out.println(y + "-" + M + "-" + d + " " + H + ":" + m + ":" + s + "." + S + " " + E);
	
	// 加减功能
	SimpleDateFormat formatter = new SimpleDateFormat("y-M-d h:m:s");
	System.out.println(formatter.format(c.getTime()));
	c.add(Calendar.DAY_OF_MONTH, 2); // 加2天
	c.add(Calendar.MINUTE, -10);  // 减10分钟
	System.out.println(formatter.format(c.getTime()));
	
	// 时区功能
	c.clear();
	c.set(2020, 2, 9, 16, 0, 0);  //这表月份要减一,3月份就是2
	c.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
	System.out.println(c.getTime());  // Calendar获取Date时会转换成当地时区
}

LocalDateTime

public static void main( String[] args )
{
	LocalDateTime dt = LocalDateTime.now();
	// ISO 8601格式
	// yyyy-MM-dd'T'HH:mm:ss.SSS
	// 2020-03-09T16:23:47.667
	System.out.println(dt);
	
	// 只需要Date或者Time
	LocalDate d = dt.toLocalDate();
	LocalTime t = dt.toLocalTime();
	
	// 设置
	// 1.parse符合IOS 8601字符串
	dt = LocalDateTime.parse("2020-03-09T16:23:47.667");
	System.out.println(dt);
	
	// 2.of设置
	dt = LocalDateTime.of(2019, 1, 1, 8, 10, 0);
	System.out.println(dt);
	
	// 3.单独设置,对比Calendar类的Set
	LocalDateTime sdt = dt.withDayOfYear(6);
	System.out.println(sdt);
	
	// 计算,和Calendar有点不同,LocalDateti不是原址改变的,dt仍然是原来值
	LocalDateTime dt2 = dt.minusDays(1).plusHours(3);
	System.out.println(dt + " " + dt2);
	
}

ZonedDateTime

LocalDateTime总是当地时区,要对时区有操作可以使用ZonedDateTime

public static void main( String[] args )
{
	// now获取当前时间
	ZonedDateTime date = ZonedDateTime.now();
	ZonedDateTime dateEST = ZonedDateTime.now(ZoneId.of("America/New_York"));  // 该时区此刻时间
	
	System.out.println(date);  // 2020-03-09T16:43:22.830+08:00[Asia/Shanghai]
	System.out.println(dateEST);  // 2020-03-09T04:43:22.833-04:00[America/New_York]

	// LocalDateTime转成ZonedDateTime,只是加了个时区信息,本身时间没变
	LocalDateTime ldt = LocalDateTime.now();
	ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/New_York"));
	System.out.println(ldt);  // 2020-03-09T16:55:13.556
	System.out.println(zdt);  // 2020-03-09T16:55:13.556-04:00[America/New_York]
	
	// ZonedDateTime转成LocalDateTime,简单丢弃时区信息
	ldt = zdt.toLocalDateTime();
	System.out.println(ldt);
	
	// 时区转换
	ZonedDateTime zonedt = ZonedDateTime.of(2020, 1, 5, 10, 0, 0, 0, ZoneId.of("America/New_York"));
	ZonedDateTime zonedt2 = zonedt.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));
	//2020-01-05T10:00-05:00[America/New_York] 2020-01-05T23:00+08:00[Asia/Shanghai]
	System.out.println(zonedt + " " + zonedt2);
}

DateTimeFormatter

SimpleTimeFormat非线程安全,DateTimeFormatter线程安全

public static void main( String[] args )
{
	DateTimeFormatter dtf = DateTimeFormatter.ofPattern("y-MM-dd H:m:s");
	System.out.println(dtf.format(LocalDateTime.now()));
	
	//自定义格式初始化LocalDateTime
	LocalDateTime dt2 = LocalDateTime.parse("2020-01-01 10:14:43", dtf);
	System.out.println(dt2);
}

Instant

Instant now = Instant.now();
System.out.println(now);
System.out.println(now.getEpochSecond());  // 秒为单位时间戳
System.out.println(now.toEpochMilli());  // 毫秒为单位时间戳

// 创建ZonedDateTime
now = Instant.ofEpochSecond(1583745633);
ZonedDateTime zdt = now.atZone(ZoneId.systemDefault());
System.out.println(zdt);

新旧API转换

// 旧转新
Instant now = new Date().toInstant();
ZonedDateTime zdt1 = ZonedDateTime.ofInstant(now, ZoneId.systemDefault());
ZonedDateTime zdt2 = now.atZone(ZoneId.systemDefault());
System.out.println(zdt1 + " " + zdt2);

// 新转旧
Date d = new Date(zdt1.toEpochSecond()*1000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(d));