日期类型,从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 对象。
第一个构造函数使用当前日期和时间来初始化对象。
第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
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(); 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 允许你选择任何用户自定义日期时间格式来运行。例如:
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 = new Date(); System.out.printf("全部日期和时间信息:%tc%n",date); System.out.printf("年-月-日格式:%tF%n",date); System.out.printf("月/日/年格式:%tD%n",date); System.out.printf("HH:MM:SS PM格式(12时制):%tr%n",date); System.out.printf("HH:MM:SS格式(24时制):%tT%n",date); 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) { 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);
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;
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的意义以此类推