Java Date总结

在日常的程序中,我们经常会用到日期时间,常常会从字符串和日期进行转换,因此本文决定深入学习一下javaDate相关部分,我这里用的jdk8.

 

一 java中的日期总述

在编程中,一般涉及到日期的操作有三种:

1日期的表示,2日期的转换,3日期的设定修改。

 

JAVAjdk1.1 之前,Date类负责这三个功能。但是jdk1.1后,java把这三个功能分成了三个类,其中:

Date类负责时间的表示,在计算机中,时间的表示是一个较大的概念,现有的系统基本都是利用从1970.1.1 00:00:00 到当前时间的毫秒数进行计时,这个时间称为epoch。在后文中如果没有明确说明,毫秒数就是指从1970年到对应时间的毫秒数。在Java Date类内部其实也是一个毫秒数,对外表现为一个Date对象,后面我将对Date类进行深入探究。

Calendar是一个工具类,负责对Date类进行修改等操作,以及从Date类中提取年月日等时间的特定信息。

DateFormat 则负责日期的转换,比如读取特定格式的字符串,转换成date对象,或者将date对象按照指定的格式转成字符串。

 

由于DateCalendarDateFormat这几个类关联不大,因此我这里分别对各个类进行探究,就不画统一的类图了。

 

二 Date类探究

为了更好的理解Date,可以从jdk中看一下Date类的结构。

Date类的方法还是比较多的,但是大多数都是Deprecated,也就是我上面所说的从Jdk1.1开始,将其他的功能都分流到了CalendarDateFormat类中。

正如我们之前讲过的,Date类内部其实是一个1970到其代表的时间之间的毫秒数,那就必然有一个filed要表示这个毫秒数,这就是 fastTime这个域的作用了。

private transient long fastTime;


在我们日常的使用Date类时,必然都要初始化一个Date对象,这时看看Date的两个剩余的构造函数,一个是无参的,一个是接收了一个long类型的毫秒数,无参构造函数其实是调用了系统的当前毫秒数。最终都是将fastTime这个属性赋值一个对应时间的毫秒数。

public Date() {
    this(System.currentTimeMillis());
}

public Date(long date) {
    fastTime = date;
}

Date类还可以对时间进行比较,比如beforeaftercompareTo等方法,都是对时间的先后进行比较的。

Date类还是保留一些工具类的方法的,比如这个静态的getMillisOf()就是获取date对象的毫秒数。

static final long getMillisOf(Date date) {
    if (date.cdate == null || date.cdate.isNormalized()) {
        return date.fastTime;
    }
    BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
    return gcal.getTime(d);
}

 Calendar

1 Calendar类的作用

在程序内部一个时间可以表示为一个毫秒数,但是对于我们日常程序中,可能需要用到这个时间点的年份,月份,小时数等详细信息,这时Calendar类就走上了舞台。

 

Calendar类前面说是一个工具类,其实它比工具类还是更深一步的,它更像是一个加强版的Date类。一般的工具类会提供一堆static方法,工具类本身并不存储对象。但是Calendar类不是像一般的工具类只提供一堆static方法,而是在其内部本身就有一个毫秒数,所以它不是对外部Date对象操作,而是对内部的毫秒数进行转化,所以说Calendar本身就包含了日期时间信息,像一个装饰者模式。

 

在Calendar类中的这个毫秒数就是下面这个field。

@SuppressWarnings("ProtectedField")
protected long          time;


Calendar的使用:

Calendar本身是一个抽象类,不能直接实例化,但是Calendar类提供一个工厂方法,即getInstance来创建一个Calendar实例,通过setTime()设定一个Calendar内部的毫秒数,之后就可以对这个毫秒数进行分析,进而得到它的年月日信息。同时,我们也可以对Calendar直接设定年月日属性,从而获取对应的Date对象。

需要注意的是,Calendar的一月是从0开始的,即你设定月份为4时,其实是五月。

下面是一个Calendar的简单示例。

Date now = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.get(Calendar.YEAR);
System.out.println("the year is "+calendar.get(Calendar.YEAR));
System.out.println("the month is "+calendar.get(Calendar.MONTH));
calendar.set(Calendar.YEAR, 2014);
calendar.set(Calendar.MONTH, 2);
calendar.set(Calendar.DAY_OF_MONTH, 12);
System.out.println("calendar date is "+calendar.getTime());


输出:

the year is 2016

the month is 9

calendar date is Wed Mar 12 22:17:50 CST 2014

 

在讲到Calendar就不可避免的涉及到java的国际化问题和时区的问题。

1) 国际化

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

你可以用如下代码看看你的系统默认地区。

Locale locale = Locale.getDefault();
locale.getCountry();
locale.getLanguage();
System.out.println("default locale is "+locale);
System.out.println("default country is "+locale.getCountry());
System.out.println("default language is "+locale.getLanguage());

比如我这里的输出就是:

default locale is zh_CN

default country is CN

default language is zh

说明了我所在的国家时CN,语言是zh

 

(2) 时区

java中用java.util.TimeZone类来表示一个时区。每一个时区都一个id,可以利用TimeZone.getAvailableIDs()这个方法获取所有的id

你可以试试利用如下代码看看你的系统默认时区。

TimeZone timeZone = TimeZone.getDefault();
System.out.println("default time zone is "+ timeZone.getDisplayName());

本文的默认时区是

default time zone is 中国标准时间


3 Calendar的工厂构造方法

前面说到,Calendar是一个抽象类,提供了static的工厂构造方法来提供一个实例。

Calendar有多个的工厂构造方法:

public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
public static Calendar getInstance(Locale aLocale)
{
    return createCalendar(TimeZone.getDefault(), aLocale);
}
public static Calendar getInstance(TimeZone zone, Locale aLocale)
{
    return createCalendar(zone, aLocale);
}

从上面的代码看出,Calendar的实例构造最终都是调用了这个方法

private static Calendar createCalendar(TimeZone zone, Locale aLocale)

这个方法接收两个参数,一个是时区,一个是地区。这个方法中通过对地区的判定返回不同的Calendar的子类(实现类),由于涉及到一些地区的问题,本文不做深究。

 

当我们有了Calendar的实例后,就可以对Date对象进行分析,提取出对应的年月日;也可以通过设定对应的年月日从而获取对应的Date对象。

 

 三 DateFormat类

1 DateFormat类的作用

DateFormat用来在Date对象和字符串之间进行转化

比如,我有一个date,想转成20131201日这种样式,或者想从2013-12-01这个字符串转成一个date对象,都可以利用DateFormat类。

 

2 DateFormat类的结构

DateFormat本身是一个抽象类,但是定义好了所有的方法,我们一般都是使用它的子类SimpleDateFormat,这也是一个标准的模板模式(template pattern)。

DateFormat中定义了众多的方法,最重要的就是parse()format(),这两个方法一个是将字符串转成Date对象,一个是将Date对象按照指定的模式进行转换字符串。

 

利用DateFormat进行转换

DateFormat虽然是个抽象类,我们在日常中可以使用它的子类SimpleDateFormat类,但DateFormat还是提供了一些static方法构建DateFormat实例,进行简单的转换日期功能。

DateFormat提供的转换格式分为两种,一种是只转换Date部分,一种是转换Date和Time两个部分。

 

先看只转换Date部分的,从代码中能看出,你可以调用getDateInstance()这个系列方法,最后其实调用的都是get方法。

这个系列主要需要注意的两个参数就是style参数和Locale参数。这个style参数,这个参数决定了你的日期格式的长度,默认的的default2,从DateFormat类中定义了几个常数,这个2就是medium,也可以设置为LONG。而最后一个参数就是地区了,决定了你的日期输出语言,中文就是年月日,英文就是单词了,我下面用一个例子说明不同参数的区别。

DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, Locale.SIMPLIFIED_CHINESE);
DateFormat format2 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.SIMPLIFIED_CHINESE);
DateFormat format3 = DateFormat.getDateInstance(DateFormat.LONG, Locale.SIMPLIFIED_CHINESE);

DateFormat format4 = DateFormat.getDateInstance(DateFormat.SHORT, Locale.ENGLISH);
DateFormat format5 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.ENGLISH);
DateFormat format6 = DateFormat.getDateInstance(DateFormat.LONG, Locale.ENGLISH);

try {
    System.out.println("format : " +format.format(new Date()));
    System.out.println("format2 : "+format2.format(new Date()));
    System.out.println("format3 : "+format3.format(new Date()));
    System.out.println("format4 : "+format4.format(new Date()));
    System.out.println("format5 : "+format5.format(new Date()));
    System.out.println("format6 : "+format6.format(new Date()));


} catch (Exception e) {
    e.printStackTrace();
}

输出:

format : 16-11-2

format2 : 2016-11-2

format3 : 2016112

format4 : 11/2/16

format5 : Nov 2, 2016

format6 : November 2, 2016

 

上面的例子,对构造DateFormat的地区和style参数就进行了说明,可以看出当style参数设为SHORT时,中英文的日期表示也是不一样的。

 

再说说DateFormat的转换日期和时间格式,即转换的Date对象同时包含日期和时间数据。这也是一个系列的方法,与上面说的getDateInstance()系列类似。

与只转换日期格式的Date有个重要的地方就是这里有两个sytle,一个是日期style,一个是时间style,可以根据自己的需要自由组合日期和时间style

我这里就不说了,有兴趣可以去看看源码。

public final static DateFormat getDateTimeInstance()
{
    return get(DEFAULT, DEFAULT, 3, Locale.getDefault(Locale.Category.FORMAT));
}
public final static DateFormat getDateTimeInstance(int dateStyle,  int timeStyle)
{
    return get(timeStyle, dateStyle, 3, Locale.getDefault(Locale.Category.FORMAT));
}
public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale)
{
    return get(timeStyle, dateStyle, 3, aLocale);
}


四 SimpleDateFormat

1 SimpleDateFormat使用

其实这个SimpleDateFormat类是我们日常转换字符串和Date对象最常用的类。

我们如果用DateFormat进行转换格式,只能用它规定的几种格式进行转换,非常的不直观,从字面我们看不出来从Date转出来的日期是怎样的格式。

但是如果用SimpleDateFormat就不一样了,在构造SimpleDateFormat我们可以直接传一个pattern,只要pattern符合要求且是合理的,就可以对Date和字符串进行转换了。

这个其实不用多说,只要来一个例子就都明白了,这里有一个坑,就是mM是不一样的,m是分钟(minute),而M是月份,用的时候一定要注意。

String dateString = "2013-02-12T12:22:33";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
System.out.println("simpleDate format " + simpleDateFormat.format(new Date()));
try {
    System.out.println("simpleDate parse "+ simpleDateFormat.parse(dateString));
} catch (ParseException e) {
    e.printStackTrace();
}

输出:

simpleDate format 2016-11-02T09:19:58

simpleDate parse Tue Feb 12 00:22:33 CST 2013

 

还有就是当parse时,只有你的字符串和SimpleDateFormatpattern完全匹配才能识别,否则报错。

 

总结:

当我们只需要一个日期时,或从系统取得,或从数据库查询,都可以放入一个Date对象。

当我们需要对Date进行详细分析,获取其中的年月日分秒各个部分的信息,用Calendar类。

当我们需要对一个字符串转成Date对象,或者想让一个Date对象按照我们预期的格式进行输出字符串时,需要用DateFormat或它的子类SimpleDateFormat。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 可以使用 `java.text.DateFormat` 类的 `format` 方法将 `java.util.Date` 对象转换为 ISO 8601 格式的日期字符串。 例如: ``` import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class Main { public static void main(String[] args) { Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); String isoDateString = dateFormat.format(date); System.out.println(isoDateString); } } ``` 输出结果将是类似于 `2022-12-29T15:45:00+08:00` 这样的日期字符串。 注意: - 要将日期格式化为 ISO 8601 格式,您需要使用 `yyyy-MM-dd'T'HH:mm:ssXXX` 格式模式。 这包括一个固定的字符串 `'T'`,用于分隔日期和时间,以及一个 `XXX` 字符,用于表示时区偏移量。 - 使用 `java.time` 包中的新日期和时间 API(Java 8 及更高版本)也可以将日期转换为 ISO 8601 格式。例如,可以使用 `DateTimeFormatter` 类的 `ISO_OFFSET_DATE_TIME` 常量来格式化日期。 希望这对您有所帮助! ### 回答2: 要将Java Date对象转换为ISO 8601格式的字符串,可以使用Java的SimpleDateFormat类和DateFormat类。以下是一个示例代码: ```java import java.text.SimpleDateFormat; import java.util.Date; import java.text.DateFormat; public class Main { public static void main(String[] args) { Date date = new Date(); // 使用SimpleDateFormat将Date对象转换为ISO 8601格式的字符串 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); String isoString = sdf.format(date); System.out.println("ISO 8601格式的字符串:" + isoString); // 使用DateFormat将ISO 8601格式的字符串转换为Date对象 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); Date isoDate = null; try { isoDate = df.parse(isoString); } catch (Exception e) { e.printStackTrace(); } System.out.println("转换回的Date对象:" + isoDate); } } ``` 上述代码首先创建一个Date对象,然后使用SimpleDateFormat将其转换为ISO 8601格式的字符串。格式字符串中的'T'表示时间和日期的分隔符,'X'表示时区。然后使用DateFormat将ISO 8601格式的字符串转换为Date对象。 注意:ISO 8601格式的字符串是一种表示日期和时间的国际标准格式,包含了日期、时间、时区的信息。 ### 回答3: 将Java Date对象转换为ISO格式,可以使用SimpleDateFormat类来完成。ISO格式指的是国际标准化组织(International Organization for Standardization)定义的日期和时间格式。 首先,创建一个SimpleDateFormat对象,并将ISO格式的日期和时间模式作为参数传递给构造函数。例如,可以使用"yyyy-MM-dd'T'HH:mm:ss.SSSZ"作为ISO格式的模式。 然后,使用SimpleDateFormat的format方法将Java Date对象转换为ISO格式的字符串。将Date对象作为参数传递给format方法,它会返回一个字符串表示该日期在ISO格式下的表示。例如: ``` Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); String isoDate = sdf.format(date); System.out.println(isoDate); ``` 输出结果可能类似于:2022-01-01T12:34:56.789+0000 这个字符串就是将Java Date对象转换为ISO格式的结果。其中,"T"表示日期和时间的分隔符,"+0000"表示时区偏移量。 需要注意的是,SimpleDateFormat类的format方法会使用当前的时区来进行转换。如果需要转换为其他时区的ISO格式,可以在创建SimpleDateFormat对象时指定时区,或者使用Calendar类来设置时区。 总结起来,将Java Date对象转换为ISO格式的方法就是使用SimpleDateFormat类的format方法,并传递日期和时间模式作为参数。这样可以方便地将日期对象转换为符合ISO标准的字符串表示。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值