java日期

java中操作时间的类主要有:Calendar、Date、DateFormat。

java时间框架

这里写图片描述

说明

milliseconds

表示毫秒,等于“实际时间” - “1970-01-01 00:00:00”。Calendar和Date都依赖milliseconds 表示时间。

Date

表示日期/时间,依赖于milliseconds 实现。
【注】在 JDK 1.1 之前,通常是通过Data操作“年月日时分秒”。不过,由于Date的相关 API 不易于实现 国际化。从 JDK 1.1 始,应该使用 Calendar 类来操作“年月日时分秒”,同时可以通过 DateFormat 类来格式化和解析日期字符串。Date 中的相应方法已废弃

Calendar

表示日期/时间,依赖于milliseconds 实现。它是一个抽象类,与Locale、TimeZone关联GregorianCalendar是Calendar的一个子类。

  • Locale代表区域;Locale的值不同时,Calendar的日期/时间也不同
  • TimeZone代表时区;不同的时区,Calendar的日期/时间也不同

DateFormat

格式化、解析日期/时间的工具类,是一个抽象类。

Calendar类

Calendar定义

Calendar是一个抽象类(只能声明,不能生成对象),它的实现采用设计模式中的工厂方法。表现在:当获取Calendar实例时,Calendar会根据传入的参数来返回相应的Calendar对象。获取Calendar实例之后,可以通过Calendar提供的一些列方法来操作日历。
JDK1.7获取Calendar实例的方法:

//Gets a calendar using the default time zone and locale
 public static Calendar getInstance()
  {
    // 调用createCalendar()创建日历
    Calendar localCalendar = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
    localCalendar.sharedZone = true;
    return localCalendar;
  }

  public static Calendar getInstance(TimeZone paramTimeZone)
  {// 调用createCalendar()创建日历
    return createCalendar(paramTimeZone, Locale.getDefault(Locale.Category.FORMAT));
  }

  public static Calendar getInstance(Locale paramLocale)
  {// 调用createCalendar()创建日历
    Calendar localCalendar = createCalendar(TimeZone.getDefaultRef(), paramLocale);
    localCalendar.sharedZone = true;
    return localCalendar;
  }

  public static Calendar getInstance(TimeZone paramTimeZone, Locale paramLocale)
  {// 调用createCalendar()创建日历
    return createCalendar(paramTimeZone, paramLocale);
  }

  private static Calendar createCalendar(TimeZone paramTimeZone, Locale paramLocale)
  {
    Object localObject = null;
    // 若地区是“th”,则返回BuddhistCalendar对象
    // 若地区是“JP”,则返回JapaneseImperialCalendar对象
    String str = paramLocale.getUnicodeLocaleType("ca");
    if (str == null)
    {
      if (("th".equals(paramLocale.getLanguage())) && ("TH".equals(paramLocale.getCountry())))
      {
        localObject = new BuddhistCalendar(paramTimeZone, paramLocale);
      }
      else localObject = new GregorianCalendar(paramTimeZone, paramLocale);
    }
    else if (str.equals("japanese"))
      localObject = new JapaneseImperialCalendar(paramTimeZone, paramLocale);
    else if (str.equals("buddhist")) {
      localObject = new BuddhistCalendar(paramTimeZone, paramLocale);
    }
    else
    {
      localObject = new GregorianCalendar(paramTimeZone, paramLocale);
    }

    return (Calendar)localObject;
  }

Calendar原理

Calendar的核心是保存了一个时间time和17个字段。通过17个字段的操作来操作时间。

//用变量表示0~17数组下标为了方便记忆。例如要表示“月”字段,不用记住月字段的标识是2,只要根据语义调用Calendar.MONTH即可。这17个字段的取值保存在fields[]数组中。
public static final int ERA = 0;//纪元;第0个字段表示纪元,取值只能是0或1,0表示BC(公元前)1表示AD(公元后)
public static final int YEAR = 1;//年;第1个字段
public static final int MONTH = 2;//月;取值为0~11,因此给月字段赋值时,要在实际月份上减1
public static final int WEEK_OF_YEAR = 3;//当前日期在本年中对应第几个星期。一年中第一个星期的值为 1。
public static final int WEEK_OF_MONTH = 4;//当前日期在本月中对应第几个星期。一个月中第一个星期的值为 1。
public static final int DATE = 5;//日;一个月中第一天的值为 1。
public static final int DAY_OF_MONTH = 5;//同"DATE",表示“日”Calendar.DATE=Calendar.DAY_OF_MONTH =5
public static final int DAY_OF_YEAR = 6;//当前日期在本年中对应第几天。一年中第一天的值为 1。
public static final int DAY_OF_WEEK = 7;//星期几;取值1~7
public static final int DAY_OF_WEEK_IN_MONTH = 8;//当前日期在本月中对应第几个星期;DATE/DAY_OF_MONTH的1~7总是对应DAY_OF_WEEK_IN_MONTH的1;8~14总是对应2...依次类推
public static final int AM_PM = 9;//上午 还是 下午AM:0  PM:1
public static final int HOUR = 10;//指示一天中的第几小时;用12小时制时钟(0-11),中午和午夜用0表示,不用12表示;早上9点与晚上9点用AM_PM区分。也可以用0~24给HOUR赋值,AM_PM会根据HOUR的值自动改变。
public static final int HOUR_OF_DAY = 11;//一天中的第几小时;用24小时制时钟.10:04:15PM的HOUR_OF_DAY 为 22
public static final int MINUTE = 12;//一小时中的第几分钟;10:04:15.250PM的MINUTE为4
public static final int SECOND = 13;//一分钟中的第几秒;10:04:15.250PM的SECOND为15
public static final int MILLISECOND = 14;//一秒中的第几毫秒;10:04:15.250PM的MILLISECOND为250
public static final int ZONE_OFFSET = 15;//毫秒为单位指示距GMT的大致偏移量
public static final int DST_OFFSET = 16;//毫秒为单位指示夏令时的偏移量
public static final int FIELD_COUNT = 17;//fields[]数组的大小

protected long time;//当前时间,单位毫秒。当前时间距离“January 1, 1970, 0:00:00 GMT”的差值。

protected int[] fields;//17个字段的取值

Calendar的操作接口

17个字段的公共接口

以下均以Calendar.MONTH为例

getMaximum(int field)

获取“指定字段的最大值”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 获取MONTH的最大值
int max = cal.getMaximum(Calendar.MONTH);//max = 11
getActualMaximum(int field)

获取“当前日期下,该字段的最大值”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 获取当前MONTH的最大值
int max = cal.getActualMaximum(Calendar.MONTH);//当前时间2016-07-30 max= 6
getMaximum与getActualMaximum对比
  • getMaximum()是指在综合所有的日期,在所有这些日期中得出的“字段最大值“。例如:getMaximum(Calendar.DATE)“获取日的最大值”综合所有的日期,得出一个月最多有31天。因此,其返回值是“31”。
  • getActualMaximum() 获取的“当前日期下,该字段的最大值”。假如当前日期为2016-02-01,getActualMaximum(Calendar.DATE)获取“日的最大值”是“29”。
getMinimum(int field)

获取“指定字段的最小值”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 获取MONTH的最小值
int min = cal.getMinimum(Calendar.MONTH);// min = 0;
getActualMinimum(int field)

获取“当前日期下,该字段的最小值”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 获取MONTH的最小值
int min = cal.getActualMinimum(Calendar.MONTH);// min = 0;
getMinimum与getActualMinimum比较

在Java默认的Calendar中,虽然 getMinimum() 和 getActualMinimum() 的含义不同;但是,它们的返回值是一样的。因为Calendar的默认是返回GregorianCalendar对象,而在GregorianCalendar.java中,getMinimum() 和 getActualMinimum() 返回值一样。

get(int field)

获取“field字段的当前值”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 获取“cal日历”的当前MONTH值
//get(int field)函数内部先通过complete()计算各个字段的值,然后在通过 internalGet(field)返回“field字段的值”,具体细节不记录。
int MONTH = cal.get(Calendar.MONTH); // MONTH = 6(当前时间2016-07-30)
set(int field, int value)

设置“field字段的当前值”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 设置“cal日历”的当前MONTH为 12月
cal.set(Calendar.MONTH, 11);//若设置的数值不在0~11之间呢????
add(int field, int value)

给“field字段的当前值”添加value,value可以为正数(日期增加),也可以是负数(日期减少).
Calendar的17个字段中,除了field=ZONE_OFFSET 时会抛出IllegalArgumentException异常;其它的字段都支持该操作。

// 获取Calendar实例,当前时间2016-07-30
Calendar cal = Calendar.getInstance();
// 给“cal日历”的当前MONTH值 “添加-17”
cal.add(Calendar.MONTH, -17);//结果为2015-02-28
roll(int field, int value)

回滚“字段的当前值”。Calendar的17个字段中,除了field=ZONE_OFFSET 时会抛出IllegalArgumentException异常;其它的字段都支持该操作。

// 获取Calendar实例,当前时间2016-07-30
Calendar cal = Calendar.getInstance();
// 给“cal日历”的当前MONTH值 “添加-17”
cal.roll(Calendar.MONTH, -17);//结果为2016-02-29
roll与add的比较

回滚Calendar中某一字段时,不更改更大的字段!例如“使用roll()修改‘MONTH’字段,不回引起‘YEAR’字段的改变。

clear(int field)

清空“字段的当前值”。所谓清空,实际上是将“field”的值设置为0;若field最小值为1,则设置为1。与isSet函数配合使用。

// 获取Calendar实例,并设置日期为“9月”
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 9);//此时cal.isSet(Calendar.MONTH)返回true
// 清空MONTH
cal.clear(Calendar.MONTH);//此时cal.isSet(Calendar.MONTH)返回false
isSet(int field)

判断“字段field”是否被设置。若调用clear()清空之后,则field变为“没有设置状态”

// 获取Calendar实例
Calendar cal = Calendar.getInstance();
// 判断MONTH是否被设置
boolean bset = cal.isSet(Calendar.MONTH);

Calendar其他函数

日期比较函数
// 比较“当前Calendar对象”和“calendar” 的日期、时区等内容是否相等。
boolean equals(Object object)
// 当前Calendar对象 是否 早于calendar
boolean before(Object calendar)
// 当前Calendar对象 是否 晚于calendar
boolean after(Object calendar)
// 比较“当前Calendar对象”和“calendar”。
// 若 早于 “calendar” 则,返回-1
// 若 相等, 则,返回0
// 若 晚于 “calendar” 则,返回1
int compareTo(Calendar anotherCalendar) 

//调用样例   cal1和cal2都是Calendar对象
boolean isEqual = cal1.equals(cal2);
boolean isBefore = cal1.before(cal2);
boolean isAfter = cal1.after(cal2);
int icompare = cal1.compareTo(cal2);
宽容函数

Calendar 有两种解释日历字段的模式: lenient 和 non-lenient。

// 设置“Calendar的宽容度”
void setLenient(boolean value)
// 获取“Calendar的宽容度”
boolean isLenient()
lenient模式:接受比它生成的日历字段范围更大范围内的值。当 Calendar 重新计算日历字段值,以便由 get() 返回这些值时,所有日历字段都被标准化。
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, -2);
System.out.println(format.format(cal.getTime()));
cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 8);
System.out.println(format.format(cal.getTime()));
cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 13);
System.out.println(format.format(cal.getTime()));
cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 24);
System.out.println(format.format(cal.getTime()));

//运行结果
2015-11-30 13:55:03
2016-09-30 13:55:03
2017-03-02 13:55:03
2018-01-30 13:55:03
non-lenient模式

当 Calendar 处于 non-lenient 模式时,如果其日历字段中存在任何不一致性,它都会抛出一个异常。 例如,GregorianCalendar 总是在 1 与月份的长度之间生成 DAY_OF_MONTH 值。如果已经设置了任何超出范围的字段值,那么在计算时间或日历字段值时,处于 non-lenient 模式下的 GregorianCalendar 会抛出一个异常。
【注】在使用set()时不会抛出,而需要在使用get()、getTimeInMillis()、getTime()、add() 和 roll() 等函数中才抛出。因为set()只是设置了一个修改标志,而get()等方法才会引起时间的重新计算,此时才会抛出异常!

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
System.out.println(cal.isLenient());
cal.set(Calendar.MONTH, 12);//MONTH的取值0~11,这里越界。
System.out.println(format.format(cal.getTime()));//此时cal是宽容的,所以不会抛出异常
cal.setLenient(false);
cal.set(Calendar.MONTH, 12);//异常到计算日期时才会抛出。即set()中不回抛出异常,而要等到get()中才会抛出异常
System.out.println(format.format(cal.getTime()));//此时cal是不宽容的,所以抛出异常

//运行结果
true
2017-01-30 14:20:59
java.lang.IllegalArgumentException: MONTH
    at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2648)
    at java.util.Calendar.updateTime(Calendar.java:3353)
    at java.util.Calendar.getTimeInMillis(Calendar.java:1782)
    at java.util.Calendar.getTime(Calendar.java:1755)
其他函数
// 设置“年月日”
final void set(int year, int month, int day)
// 设置“年月日时分”
final void set(int year, int month, int day, int hourOfDay, int minute, int second)
// 设置“年月日时分秒”
final void set(int year, int month, int day, int hourOfDay, int minute)
// 获取Calendar对应的日期
final Date getTime()
// 设置Calendar为date
final void setTime(Date date)
// 获取Calendar对应的时区
TimeZone getTimeZone()
// 设置Calendar对应的时区
void setTimeZone(TimeZone timezone)
// 获取Calendar对应的milliscondes值,就是“Calendar当前日期”距离“1970-01-01 0:00:00 GMT”的毫秒数
long getTimeInMillis()
// 设置Calendar对应的milliscondes值
void setTimeInMillis(long milliseconds)

// 克隆Calendar   java中对象传的是引用,在函数中利用clone函数生成一个临时变量,对临时变量的操作不会影响原参数
Object clone()
//clone()举例   获取“下一个月的天数”
public static int getNextMonthDays(Calendar cal) {
    Calendar tmpCal = (Calendar)cal.clone();     // 克隆cal。后面对tmpCal操作,就不会改变cal
    tmpCal.add(Calendar.MONTH, 1);               // 设为“下一个月”
    return tmpCal.getActualMaximum(Calendar.DATE);    
} 

Date类

Date 是表示时间的类,一个Date对象表示一个特定的瞬间,能精确到毫秒.


Date和Calendar的转换

Date转Calendar

// 新建date,且日期/时间为2013-07-30 14:22:30
Date date = new Date(116, 6, 30, 14, 22, 30);//---该方法已废弃
// 新建Calendar对象,并设置日期为date
Calendar cal = Calendar.getInstance();
cal.setTime(date);

Calendar转Date

// 新建Calendar对象
Calendar cal = Calendar.getInstance();
// 获取Calendar对应的Date
Date date = cal.getTime();

由于Date的相关 API 不易于实现国际化,不再记录其相关操作。可将Date转换为Calendar对象进行操作。


GMT、UTC、时区的关系

//TODO

DateFormat

DateFormat是一个抽象类,通过DateFormat的 getTimeInstance(), getDateInstance()和getDateTimeInstance() 获取DateFormat实例时,实际上是返回的SimpleDateFormat对象。DateFormat的作用是将Date转换成String字符串并且有很多函数在SimpleDateFormat中定义。DateFormat提供的功能非常有限,它只能支持FULL、LONG、MEDIUM 和 SHORT 这4种格式 ,主要介绍SimpleDateFormat。

SimpleDateFormat

SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。


构造函数

SimpleDateFormat()
SimpleDateFormat(String pattern)
SimpleDateFormat(String template, DateFormatSymbols value)
SimpleDateFormat(String template, Locale locale)

日期和时间模式

时间/日期的格式由模式字母组成,模式字母通常是重复的,其数量确定其精确表示

模式字母表

//TODO


格式化

日期数据的格式化

SimpleDateFormat bartDateFormat = new SimpleDateFormat("EEEE-MMMM-dd-yyyy"); 
Date date = new Date(); 
System.out.println(bartDateFormat.format(date)); //输出星期六-9月-29日-2001年

文本数据解析成日期对象

//Date原始格式
String dateStr = "Thu Jul 28 20:27:42 CST 2016";
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");  
try { 
    Date date = format.parse(dateStr ); //
} catch (ParseException e) {
     e.printStackTrace();
}

dateStr = "Fri Feb 28 09:07:42 +0800 2014";
format  = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZZ yyyy", Locale.ENGLISH);
try {
     Date date = format .parse(dateStr);
} catch (ParseException e) {
     e.printStackTrace();
}

String dateStr = "9-29-2001";
SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy");  
try { 
    Date date = format.parse(dateStringToParse); //
} catch (ParseException e) {
     e.printStackTrace();
}

Loacal

Locale 表示地区。每一个Locale对象都代表了一个特定的地理、政治和文化地区。

Locale对象的3种创建方式

获取默认的Locale

Locale locale = Locale.getDefault()

调用Locale的静态对象

//Locale.java中提供了以下静态对象
public static final Locale CANADA
public static final Locale CANADA_FRENCH
public static final Locale CHINA
public static final Locale CHINESE
public static final Locale ENGLISH
public static final Locale FRANCE
public static final Locale FRENCH
public static final Locale GERMAN
public static final Locale GERMANY
public static final Locale ITALIAN
public static final Locale ITALY
public static final Locale JAPAN
public static final Locale JAPANESE
public static final Locale KOREA
public static final Locale KOREAN
public static final Locale PRC
public static final Locale ROOT
public static final Locale SIMPLIFIED_CHINESE
public static final Locale TAIWAN
public static final Locale TRADITIONAL_CHINESE
public static final Locale UK
public static final Locale US

//调用方法
Locale locale = Locale.SIMPLIFIED_CHINESE//对应"中国(大陆)"

通过构造函数创建Locale对象

Locale(String language)
Locale(String language, String country)
Locale(String language, String country, String variant)

查看Locale支持的区域:

Locale[] locale = Locale.getAvailableLocales();
for (Locale la : locale) {
    System.out.println(la);
}

//部分输出结果
ja_JP
ar_JO
ar_SY
en
fr_BE
es_PA
mt_MT
es_VE
bg
zh_TW
it
ko
en_US

//结果分析:以ja_JP为例,ja代表language,这里指日语;JP代表country,这里指日本。
//创建语言是日语,国家是日本的Locale对象
Locale locale = new Locale("ja", "JP");
//创建语言是英语的Locale对象
Locale locale = new Locale("en");

Date date = new Date();
SimpleDateFormat format = null;
// 创建“英文/美国”的Locale
Locale localeUS = new Locale("en", "US");
format = new SimpleDateFormat("EEE yyyy-MM-dd HH:mm:ss", localeUS);
// 获取“简体中文”对应的date字符串
String cn = format.format(date);
format = new SimpleDateFormat("EEE yyyy-MM-dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE); // 创建“简体中文”的Locale
// 获取“英文/美国”对应的date字符串
String us = format.format(date);
System.out.println(cn);
System.out.println(us);

//输出结果
Sat 2016-07-30 16:12:54
星期六 2016-07-30 16:12:54

TimeZone

TimeZone 表示时区偏移量,也可以计算夏令时。

TimeZone对象的两种创建方式

获取默认的TimeZone

TimeZone tz = TimeZone.getDefault()

使用 getTimeZone(String id) 方法获取TimeZone对象

// 获取 “GMT+08:00”对应的时区
TimeZone china = TimeZone.getTimeZone("GMT+:08:00");

查看该方式支持的所有id

String[] ids = TimeZone.getAvailableIDs();
for (String id:ids) {
    System.out.println(id);
}

//设置时区
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
format.setTimeZone(timeZone);
format.format(date);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值