日期类型,从1970年计,每过一毫秒就+1.不是+1s,所以也没法用膜法续命.

所有的数据类型,无论是整数,布尔,浮点数还是字符串,最后都需要以数字的形式表现出来。 日期类型也不例外,换句话说,一个日期,比如2020年10月1日,在计算机里,会用一个数字来代替。 那么最特殊的一个数字,就是零. 零这个数字,就代表Java中的时间原点,其对应的日期是1970年1月1日 8点0分0秒 。 (为什么是8点,因为中国的太平洋时区是UTC-8,刚好和格林威治时间差8个小时) 为什么对应1970年呢? 因为1969年发布了第一个 UNIX 版本:AT&T,综合考虑,当时就把1970年当做了时间原点。 所有的日期,都是以为这个0点为基准,每过一毫秒,就+1。

Java 日期时间

java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。

第一个构造函数使用当前日期和时间来初始化对象。

1
Date( )

第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。

1
Date(long millisec)

Date对象创建以后,可以调用下面的方法。

序号 方法和描述
1 boolean after(Date date) 若当调用此方法的Date对象在指定日期之后返回true,否则返回false。
2 boolean before(Date date) 若当调用此方法的Date对象在指定日期之前返回true,否则返回false。
3 Object clone( ) 返回此对象的副本。
4 int compareTo(Date date) 比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。
5 int compareTo(Object obj) 若obj是Date类型则操作等同于compareTo(Date) 。否则它抛出ClassCastException。
6 boolean equals(Object date) 当调用此方法的Date对象和指定日期相等时候返回true,否则返回false。
7 long getTime( ) 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
8 int hashCode( ) 返回此对象的哈希码值。
9 void setTime(long time) 用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。
10 String toString( ) 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package date;

//
import java.util.Date;

public class TestDate {

public static void main(String[] args) {

// 当前时间
Date d1 = new Date();
System.out.println("当前时间:");
System.out.println(d1);
System.out.println();
// 从1970年1月1日 早上8点0分0秒 开始经历的毫秒数
Date d2 = new Date(5000);
System.out.println("从1970年1月1日 早上8点0分0秒 开始经历了5秒的时间");
System.out.println(d2);

}
}

日期比较

Java使用以下三种方法来比较两个日期:

  • 使用 getTime() 方法获取两个日期(自1970年1月1日经历的毫秒数值),然后比较这两个值。
  • 使用方法 before(),after() 和 equals()。例如,一个月的12号比18号早,则 new Date(99, 2, 12).before(new Date (99, 2, 18)) 返回true。
  • 使用 compareTo() 方法,它是由 Comparable 接口定义的,Date 类实现了这个接口。

创建一个从1995.1.1 00:00:00 到 1995.12.31 23:59:59 之间的随机日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class TestDate {
public static void main(String[] args) {
String start = "1995/1/1 0:0:0";
String end = "1995/12/31 23:59:59";
long sd = stringToDateLong(start);
long se = stringToDateLong(end);
long rangeRandom = genRandomDate(se, sd);
Date ranDate = new Date(rangeRandom);
System.out.println(ranDate);
}

public static long stringToDateLong(String d) {
long dlong = 0;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
try {
Date dd = sdf.parse(d);
long dLong = dd.getTime();
return dLong;
} catch (ParseException e) {
e.printStackTrace();
}
return dlong;
}

public static long genRandomDate(long max, long min) {
long ranLong = min + (long) (Math.random() * (max - min));
return ranLong;

}
}

使用1970年-2000年之间的随机日期初始化该数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.TreeSet;

public class TestDate {
static String start = "1997/1/1 0:0:0";
static String end = "2000/12/31 23:59:59";
static long sd = stringToDateLong(start);
static long se = stringToDateLong(end);
static TreeSet<Date> dateSet = new TreeSet<>() {
@Override
public String toString() {
String out = "";
for (Date date : dateSet
) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(date) + "\n";
out += str;
}
return out;
}
};

public static void main(String[] args) {
init();
System.out.println(dateSet.toString());
}


public static void init() {

for (int i = 0; i < 9; i++) {
long rangeRandom = genRandomDate(se, sd);
dateSet.add(new Date(rangeRandom));
}
}

public static long stringToDateLong(String d) {
long dlong = 0;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
try {
Date dd = sdf.parse(d);
long dLong = dd.getTime();
return dLong;
} catch (ParseException e) {
e.printStackTrace();
}
return dlong;
}

public static long genRandomDate(long max, long min) {
long ranLong = min + (long) (Math.random() * (max - min));
return ranLong;

}
}

将日期转为字符串

使用 SimpleDateFormat 格式化日期

SimpleDateFormat 是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat 允许你选择任何用户自定义日期时间格式来运行。例如:

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.*;
import java.text.*;

public class DateDemo {
public static void main(String args[]) {

Date dNow = new Date( );
SimpleDateFormat ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");

System.out.println("Current Date: " + ft.format(dNow));
}
}

关键字是SimpleDateFormat对象的format方法.

日期和时间的格式化编码

时间模式字符串用来指定时间格式。在此模式中,所有的 ASCII 字母被保留为模式字母,定义如下:

字母 描述 示例
G 纪元标记 AD
y 四位年份 2001
M 月份 July or 07
d 一个月的日期 10
h A.M./P.M. (1~12)格式小时 12
H 一天中的小时 (0~23) 22
m 分钟数 30
s 秒数 55
S 毫秒数 234
E 星期几 Tuesday
D 一年中的日子 360
F 一个月中第几周的周几 2 (second Wed. in July)
w 一年中第几周 40
W 一个月中第几周 1
a A.M./P.M. 标记 PM
k 一天中的小时(1~24) 24
K A.M./P.M. (0~11)格式小时 10
z 时区 Eastern Standard Time
文字定界符 Delimiter
单引号 `

使用printf格式化日期

printf 方法可以很轻松地格式化时间和日期。使用两个字母格式,它以 %t 开头并且以下面表格中的一个字母结尾。

转 换 符 说 明 示 例
c 包括全部日期和时间信息 星期六 十月 27 14:21:20 CST 2007
F “年-月-日”格式 2007-10-27
D “月/日/年”格式 10/27/07
r “HH:MM:SS PM”格式(12时制) 02:25:51 下午
T “HH:MM:SS”格式(24时制) 14:28:16
R “HH:MM”格式(24时制) 14:28

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Date;

public class DateDemo {

public static void main(String args[]) {
// 初始化 Date 对象
Date date = new Date();

//c的使用
System.out.printf("全部日期和时间信息:%tc%n",date);
//f的使用
System.out.printf("年-月-日格式:%tF%n",date);
//d的使用
System.out.printf("月/日/年格式:%tD%n",date);
//r的使用
System.out.printf("HH:MM:SS PM格式(12时制):%tr%n",date);
//t的使用
System.out.printf("HH:MM:SS格式(24时制):%tT%n",date);
//R的使用
System.out.printf("HH:MM格式(24时制):%tR",date);
}
}

将字符串转为日期

关键字为parse,模式(yyyy/MM/dd HH:mm:ss)需要和字符串格式保持一致,如果不一样就会抛出解析异常ParseException.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package date;

//
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestDate {

public static void main(String[] args) {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy/MM/dd HH:mm:ss" );

String str = "2016/1/5 12:12:12";

try {
Date d = sdf.parse(str);
System.out.printf("字符串 %s 通过格式 yyyy/MM/dd HH:mm:ss %n转换为日期对象: %s",str,d.toString());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

Calendar类

Calendar类用于设置和获取日期数据的特定部分等,常用于进行“翻日历”,比如下个月的今天是多久.Calendar类是一个抽象类,不能实例化,需要使用getInstance()方法来获取.而且该方法还是用的单例模式.主要方法:add方法,在原日期上增加年/月/日和set方法,直接设置年/月/日

Calendar类对象字段类型

Calendar类中用以下这些常量表示不同的意义,jdk内的很多类其实都是采用的这种思想

常量 描述
Calendar.YEAR 年份
Calendar.MONTH 月份
Calendar.DATE 日期
Calendar.DAY_OF_MONTH 日期,和上面的字段意义完全相同
Calendar.HOUR 12小时制的小时
Calendar.HOUR_OF_DAY 24小时制的小时
Calendar.MINUTE 分钟
Calendar.SECOND
Calendar.DAY_OF_WEEK 星期几

获得相关数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Calendar c1 = Calendar.getInstance();
// 获得年份
int year = c1.get(Calendar.YEAR);
// 获得月份
int month = c1.get(Calendar.MONTH) + 1;
// 获得日期
int date = c1.get(Calendar.DATE);
// 获得小时
int hour = c1.get(Calendar.HOUR_OF_DAY);
// 获得分钟
int minute = c1.get(Calendar.MINUTE);
// 获得秒
int second = c1.get(Calendar.SECOND);
// 获得星期几(注意(这个与Date类是不同的):1代表星期日、2代表星期1、3代表星期二,以此类推)
int day = c1.get(Calendar.DAY_OF_WEEK);

修改相关数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
* @author YL
*/
public class CalendarTest {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public static void main(String[] args) {
Calendar c = Calendar.getInstance();
Date now = c.getTime();
// 当前日期
System.out.println("当前日期:\t" + sdf.format(c.getTime()));

// 下个月的今天
c.setTime(now);
c.add(Calendar.MONTH, 1);
System.out.println("下个月的今天:\t" + sdf.format(c.getTime()));

// 去年的今天
c.setTime(now);
c.add(Calendar.YEAR, -1);
System.out.println("去年的今天:\t" + sdf.format(c.getTime()));

// 上个月的第三天
c.setTime(now);
c.add(Calendar.MONTH, -1);
c.set(Calendar.DATE, 3);
System.out.println("上个月的第三天:\t" + sdf.format(c.getTime()));

}
}

利用字段类型设置

Set设置

如果只设定某个字段,例如日期的值,则可以使用如下set方法:

1
public void set(int field,int value)

把 c1对象代表的日期设置为10号,其它所有的数值会被重新计算

1
c1.set(Calendar.DATE,10);

把c1对象代表的年份设置为2008年,其他的所有数值会被重新计算

1
c1.set(Calendar.YEAR,2008);

其他字段属性set的意义以此类推

也可以在set方法中直接指定具体数值

void set(int year, int month, int date, int hour, int minute, int second)  //设置年、月、日、小时、分钟、秒的值。

Add设置

1
Calendar c1 = Calendar.getInstance();

把c1对象的日期加上10,也就是c1也就表示为10天后的日期,其它所有的数值会被重新计算

1
c1.add(Calendar.DATE, 10);

把c1对象的日期减去10,也就是c1也就表示为10天前的日期,其它所有的数值会被重新计算

1
c1.add(Calendar.DATE, -10);

其他字段属性的add的意义以此类推