Java日期时间

Date类

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

Date()

第二个构造函数接收一个参数,该参数是从197011日起的毫秒数:

Date(long millisec)

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

  • boolean after(Date date):若当前调用此方法的Date对象在指定日期之后,就返回true,否则返回false
  • boolean before(Date date):若当前调用此方法的Date对象在指定日期之前,就返回true,否则返回false
  • Object clone():返回此对象的副本。
  • int compareTo(Date date):比较当前调用此方法的Date对象和指定日期,两者相等时候返回0;调用对象在指定日期之前则返回负数;调用对象在指定日期之后则返回正数。
  • int compareTo(Object obj):若objDate类型,则操作等同于compareTo(Date),否则它抛出ClassCastException
  • boolean equals(Object date):当前调用此方法的Date对象和指定日期相等时,就返回true,否则返回false
  • long getTime():返回自19701100:00:00 GMT以来此Date对象表示的毫秒数。
  • int hashCode():返回此对象的哈希码值。
  • void setTime(long time):用自19701100:00:00 GMT以后time毫秒数设置时间和日期。
  • String toString():把此Date对象转换为以下形式的String
dow mon dd hh:mm:ss zzz yyyy

其中dow是一周中的某一天(即SunMonTueWedThuFriSat)。

获取当前日期时间

  Java使用Date对象的toString方法来打印当前日期和时间:

import java.util.Date;

public class DateDemo {
    public static void main(String args[]) {
        /* 初始化Date对象 */
        Date date = new Date();
        /* 使用toString显示日期时间 */
        System.out.println(date.toString());
    }
}

执行结果:

Mon May 28 13:19:41 JST 2018

日期比较

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

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

SimpleDateFormat

  SimpleDateFormat允许用户自定义日期时间格式:

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));
    }
}

执行结果:

Current Date: 周一 2018.05.28 at 01:29:52 下午 JST

SimpleDateFormat这一行代码确立了转换的格式,其中yyyy是完整的公元年,MM是月份,dd是日期,HH:mm:ss。注意,有的格式大写,有的格式小写,例如MM是月份,mm是分;HH24小时制,而hh12小时制。
  有时我们希望得到Date的特定格式(例如20020324),可以使用以下方法:

import java.text.SimpleDateFormat;

java.util.Date date = new java.util.Date();
/* 如果希望得到YYYYMMDD的格式 */
SimpleDateFormat sy1 = new SimpleDateFormat("yyyyMMdd");
String dateFormat = sy1.format(date);
/* 如果希望分开得到年、月、日 */
SimpleDateFormat sy = new SimpleDateFormat("yyyy");
SimpleDateFormat sm = new SimpleDateFormat("MM");
SimpleDateFormat sd = new SimpleDateFormat("dd");
String syear = sy.format(date);
String smon = sm.format(date);
String sday = sd.format(date);

日期和时间的格式化编码

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

字母描述示例
G纪元标记AD
y四位年份2001
M月份July or 07
d一个月的日期10
hA.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
aA.M./P.M.标记PM
k一天中的小时(1~24)24
KA.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
rHH:MM:SS PM格式(12时制)02:25:51 下午
THH:MM:SS格式(24时制)14:28:16
RHH:MM格式(24时制)14:28

代码如下:

import java.util.Date;

public class DateDemo {
    public static void main(String args[]) {
        Date date = new Date(); /* 初始化Date对象 */
        System.out.printf("全部日期和时间信息:%tc%n", date); /* “c”的使用 */
        System.out.printf("年-月-日格式:%tF%n", date); /* “f”的使用 */
        System.out.printf("月/日/年格式:%tD%n", date); /* “d”的使用 */
        System.out.printf("HH:MM:SS PM格式(12时制):%tr%n", date); /* “r”的使用 */
        System.out.printf("HH:MM:SS格式(24时制):%tT%n", date); /* “t”的使用 */
        System.out.printf("HH:MM格式(24时制):%tR", date); /* “R”的使用 */
    }
}

执行结果:

全部日期和时间信息:周一 528 13:44:57 JST 2018
年-月-日格式:2018-05-28
月/日/年格式:05/28/18
HH:MM:SS PM格式(12时制):01:44:57 下午
HH:MM:SS格式(24时制):13:44:57
HH:MM格式(24时制):13:44

  如果你需要重复提供日期,那么利用这种方式来格式化它的每一部分就有点复杂了。因此,可以利用一个格式化字符串指出要被格式化的参数的索引。索引必须紧跟在%后面,而且必须以$结束:

import java.util.Date;

public class DateDemo {
    public static void main(String args[]) {
        /* 初始化Date对象 */
        Date date = new Date();
        /* 使用toString显示日期和时间 */
        System.out.printf("%1$s %2$tB %2$td, %2$tY", "Due date:", date);
    }
}

执行结果:

Due date: 五月 29, 2018

  格式为%t表示输出时间日期类型,%t之后用y表示输出日期的二位数的年份(例如99),用m表示输出日期的月份,用d表示输出日期的日号,用Y表示输出日期的四位数的年份(例如1999),用B表示输出日期的月份的完整名,用b表示输出日期的月份的简称,用D表示以%tm/%td/%ty的格式输出日期,用F表示以%tY-%tm-%td的格式输出日期。
  用H表示输出时间的时(24进制),用I表示输出时间的时(12进制),用M表示输出时间分,用S表示输出时间的秒,用L表示输出时间的秒中的毫秒数,用p表示输出时间的是上午还是下午,用R表示以%tH:%tM的格式输出时间,用T表示以%tH:%tM:%tS的格式输出时间,用r表示以%tI:%tM:%tS %Tp的格式输出时间,用A表示输出日期的全称,用a表示输出日期的星期简称。
  定义日期格式的转换符可以使日期通过指定的转换符生成新字符串:

import java.util.*;

public class DateDemo {
    public static void main(String args[]) {
        Date date = new Date();
        /* b的使用,月份简称 */
        String str = String.format(Locale.US, "英文月份简称:%tb", date);
        System.out.println(str);
        System.out.printf("本地月份简称:%tb%n", date);
        /* B的使用,月份全称 */
        str = String.format(Locale.US, "英文月份全称:%tB", date);
        System.out.println(str);
        System.out.printf("本地月份全称:%tB%n", date);
        /* a的使用,星期简称 */
        str = String.format(Locale.US, "英文星期的简称:%ta", date);
        System.out.println(str);
        /* A的使用,星期全称 */
        System.out.printf("本地星期的简称:%tA%n", date);
        /* C的使用,年前两位 */
        System.out.printf("年的前两位数字(不足两位前面补0):%tC%n", date);
        /* y的使用,年后两位 */
        System.out.printf("年的后两位数字(不足两位前面补0):%ty%n", date);
        /* j的使用,一年的天数 */
        System.out.printf("一年中的天数(即年的第几天):%tj%n", date);
        /* m的使用,月份 */
        System.out.printf("两位数字的月份(不足两位前面补0):%tm%n", date);
        /* d的使用,日(二位,不够补零) */
        System.out.printf("两位数字的日(不足两位前面补0):%td%n", date);
        /* e的使用,日(一位不补零) */
        System.out.printf("月份的日(前面不补0):%te", date);
    }
}

执行结果:

英文月份简称:May
本地月份简称:5月
英文月份全称:May
本地月份全称:五月
英文星期的简称:Tue
本地星期的简称:星期二
年的前两位数字(不足两位前面补0):20
年的后两位数字(不足两位前面补0):18
一年中的天数(即年的第几天):149
两位数字的月份(不足两位前面补0):05
两位数字的日(不足两位前面补0):29
月份的日(前面不补0):29

解析字符串为时间

  SimpleDateFormat类有一些附加的方法,特别是parse,它试图按照给定的SimpleDateFormat对象的格式化存储来解析字符串:

import java.util.*;
import java.text.*;

public class DateDemo {
    public static void main(String args[]) {
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd");
        String input = args.length == 0 ? "1818-11-11" : args[0];
        System.out.print(input + " Parses as ");

        Date t;
        try {
            t = ft.parse(input);
            System.out.println(t);
        } catch (ParseException e) {
            System.out.println("Unparseable using " + ft);
        }
    }
}

执行结果:

$ java DateDemo
1818-11-11 Parses as Wed Nov 11 00:00:00 GMT 1818
$ java DateDemo 2007-12-01
2007-12-01 Parses as Sat Dec 01 00:00:00 GMT 2007

Java休眠(sleep)

  sleep使当前线程进入停滞状态(阻塞当前线程),让出CPU的使用权,目的是不让当前线程独自霸占CPU资源。你可以让程序休眠一毫秒的时间,或者到您的计算机的寿命长的任意段时间。下面的程序会休眠3秒:

import java.util.*;

public class SleepDemo {
    public static void main(String args[]) {
        try {
            System.out.println(new Date() + "\n");
            Thread.sleep(1000 * 3); /* 休眠3秒 */
            System.out.println(new Date() + "\n");
        } catch (Exception e) {
            System.out.println("Got an exception!");
        }
    }
}

测量时间

  下面的一个例子表明如何测量时间间隔(以毫秒为单位):

import java.util.*;

public class DiffDemo {
    public static void main(String args[]) {
        try {
            long start = System.currentTimeMillis();
            System.out.print(new Date() + "\n");
            Thread.sleep(5 * 60 * 10);
            System.out.print(new Date() + "\n");
            long end = System.currentTimeMillis();
            long diff = end - start;
            System.out.println("Difference is:" + diff);
        } catch (Exception e) {
            System.out.println("Got an exception!");
        }
    }
}

执行结果:

Tue May 29 08:18:48 JST 2018
Tue May 29 08:18:51 JST 2018
Difference is:3059

Calendar类

  我们现在已经能够格式化并创建一个日期对象了,但是如何才能设置和获取日期数据的特定部分呢(比如说小时或者分钟)?又如何在日期的这些部分加上或者减去值呢?答案是使用Calendar类。
  Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些。Calendar类是一个抽象类,创建对象时只需要使用getInstance方法即可。
  创建一个代表系统当前日期的Calendar对象:

Calendar c = Calendar.getInstance(); /* 默认是当前日期 */

  创建一个指定日期的Calendar对象:需要首先创建一个Calendar的对象,然后再设定该对象中的年月日参数:

/* 创建一个代表2009年6月12日的Calendar对象 */
Calendar c1 = Calendar.getInstance();
c1.set(2009, 6 - 1, 12);

Calendar类对象字段类型

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

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

Calendar类对象信息的设置

  Set函数原型如下:

public final void set(int year, int month, int date);

调用方法:

Calendar c1 = Calendar.getInstance();
/* 把Calendar对象c1的年月日分别设置为2009、6、12 */
c1.set(2009, 6 - 1, 12);

  利用字段类型设置:如果只设定某个字段(例如日期的值),可以使用如下set方法:

public void set(int field, int value);

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

c1.set(Calendar.DATE, 10);

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

c1.set(Calendar.YEAR, 2008);

其他字段属性set的意义以此类推。
  Add设置:把c1对象的日期加上10,也就是c1也就表示为10天后的日期,其它所有的数值会被重新计算:

c1.add(Calendar.DATE, 10);

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

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

Calendar类对象信息的获得

  代码如下:

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,以此类推 */
int day = c1.get(Calendar.DAY_OF_WEEK);

GregorianCalendar类

  Calendar类实现了公历日历,GregorianCalendarCalendar类的一个具体实现。CalendargetInstance方法返回一个默认用当前的语言环境和时区初始化的GregorianCalendar对象。GregorianCalendar定义了两个字段(ADBC),这是代表公历定义的两个时代。下面列出GregorianCalendar对象的几个构造方法:

  • GregorianCalendar():在具有默认语言环境的默认时区内使用当前时间构造一个默认的GregorianCalendar
  • GregorianCalendar(int year, int month, int date):在具有默认语言环境的默认时区内构造一个带有给定日期设置的GregorianCalendar
  • GregorianCalendar(int year, int month, int date, int hour, int minute):在具有默认语言环境的默认时区内构造一个具有给定日期和时间设置的GregorianCalendar
  • GregorianCalendar(int year, int month, int date, int hour, int minute, int second):在具有默认语言环境的默认时区内构造一个具有给定日期和时间设置的GregorianCalendar
  • GregorianCalendar(Locale aLocale):在具有给定语言环境的默认时区内构造一个基于当前时间的GregorianCalendar
  • GregorianCalendar(TimeZone zone):在具有默认语言环境的给定时区内构造一个基于当前时间的GregorianCalendar
  • GregorianCalendar(TimeZone zone, Locale aLocale):在具有给定语言环境的给定时区内构造一个基于当前时间的GregorianCalendar

这里是GregorianCalendar类提供的一些方法:

  • void add(int field, int amount):根据日历规则,将指定的(有符号的)时间量添加到给定的日历字段中。
  • protected void computeFields():转换UTC毫秒值为时间域值。
  • protected void computeTime():覆盖Calendar,转换时间域值为UTC毫秒值。
  • boolean equals(Object obj):比较此GregorianCalendar与指定的Object
  • int get(int field):获取指定字段的时间值。
  • int getActualMaximum(int field):返回当前日期给定字段的最大值。
  • int getActualMinimum(int field):返回当前日期给定字段的最小值。
  • int getGreatestMinimum(int field):返回此GregorianCalendar实例给定日历字段的最高的最小值。
  • Date getGregorianChange():获得格里高利历的更改日期。
  • int getLeastMaximum(int field):返回此GregorianCalendar实例给定日历字段的最低的最大值。
  • int getMaximum(int field):返回此GregorianCalendar实例的给定日历字段的最大值。
  • Date getTime():获取日历当前时间。
  • long getTimeInMillis():获取用长整型表示的日历的当前时间。
  • TimeZone getTimeZone():获取时区。
  • int getMinimum(int field):返回给定字段的最小值。
  • int hashCode():重写hashCode
  • boolean isLeapYear(int year):确定给定的年份是否为闰年。
  • void roll(int field, boolean up):在给定的时间字段上添加或减去(上/下)单个时间单元,不更改更大的字段。
  • void set(int field, int value):用给定的值设置时间字段。
  • void set(int year, int month, int date):设置年、月、日的值。
  • void set(int year, int month, int date, int hour, int minute):设置年、月、日、小时、分钟的值。
  • void set(int year, int month, int date, int hour, int minute, int second):设置年、月、日、小时、分钟、秒的值。
  • void setGregorianChange(Date date):设置GregorianCalendar的更改日期。
  • void setTime(Date date):用给定的日期设置Calendar的当前时间。
  • void setTimeInMillis(long millis):用给定的long型毫秒数设置Calendar的当前时间。
  • void setTimeZone(TimeZone value):用给定时区值设置当前时区。
  • String toString():返回代表日历的字符串。
import java.util.*;

public class GregorianCalendarDemo {
    public static void main(String args[]) {
        String months[] = {
            "Jan", "Feb", "Mar", "Apr",
            "May", "Jun", "Jul", "Aug",
            "Sep", "Oct", "Nov", "Dec"
        };

        int year;
        /* 初始化Gregorian日历,使用当前时间和日期,默认为本地时间和时区 */
        GregorianCalendar gcalendar = new GregorianCalendar();
        /* 显示当前时间和日期的信息 */
        System.out.print("Date:");
        System.out.print(months[gcalendar.get(Calendar.MONTH)]);
        System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
        System.out.println(year = gcalendar.get(Calendar.YEAR));
        System.out.print("Time:");
        System.out.print(gcalendar.get(Calendar.HOUR) + ":");
        System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
        System.out.println(gcalendar.get(Calendar.SECOND));

        if (gcalendar.isLeapYear(year)) { /* 测试当前年份是否为闰年 */
            System.out.println("当前年份是闰年");
        } else {
            System.out.println("当前年份不是闰年");
        }
    }
}

执行结果:

Date:May 29 2018
Time:8:57:12
当前年份不是闰年

  Calender的月份是从0开始的,但日期和年份是从1开始的:

import java.util.Calendar;

public class Test {
    public static void main(String[] args) {
        Calendar c1 = Calendar.getInstance();
        c1.set(2017, 1, 1);
        System.out.println(c1.get(Calendar.YEAR)
            + "-" + c1.get(Calendar.MONTH)
            + "-" + c1.get(Calendar.DATE));
        c1.set(2017, 1, 0);
        System.out.println(c1.get(Calendar.YEAR)
            + "-" + c1.get(Calendar.MONTH)
            + "-" + c1.get(Calendar.DATE));
    }
}

执行结果:

2017-1-1
2017-0-31

可见,将日期设为0以后,月份变成了上个月,但月份可以为0。把月份改为2试试:

import java.util.Calendar;

public class Test {
    public static void main(String[] args) {
        Calendar c1 = Calendar.getInstance();
        c1.set(2017, 2, 1);
        System.out.println(c1.get(Calendar.YEAR)
            + "-" + c1.get(Calendar.MONTH)
            + "-" + c1.get(Calendar.DATE));
        c1.set(2017, 2, 0);
        System.out.println(c1.get(Calendar.YEAR)
            + "-" + c1.get(Calendar.MONTH)
            + "-" + c1.get(Calendar.DATE));
    }
}

执行结果:

2017-2-1
2017-1-28

可以看到上个月的最后一天是28号,所以Calendar.MONTH1的时候是2月。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值