java日期

来源:互联网 发布:淘宝买守望先锋亚服 编辑:程序博客网 时间:2024/06/05 21:05
参考文档:http://www.apihome.cn/api/java/SimpleDateFormat.html
DateFormat
Java时间设置和计算的职责给了Calendar,把格式化的职责分配给了DateFormat,DateFormat呢,也是抽象类,创建对象的方式,也是getInstance()。创建出来什么样的对象,也是跟环境有关。而且,它不但可以格式化,还可以把字符串转化解析为Date对象。蛋疼的问题出现了,它格式化,只能格式化Date对象,而不能格式化Calendar对象,用之前,还要转化一下~~(⊙o⊙)…,可是,Date类没有时区啊!!
也就稍微试一下吧

System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.CHINESE).format(new Date()));
输出:
2017年3月14日 星期二 下午01时51分35秒 CST
感觉DateFormat设计的,额,有点蛋疼,设计了很多getInstance,却让我觉得,都不怎么好用,也许是我太笨了。。。


SimpleDateFormat

SimpleDateFormat的对象创建,需要指定一个格式化(解析)的模板,也可以专门指定一个Locale对象。当然,你也可以什么都不指定,让它给你默认的模式。

        SimpleDateFormat fmtChina = new SimpleDateFormat("E",Locale.SIMPLIFIED_CHINESE);
        SimpleDateFormat fmtUS = new SimpleDateFormat("E",Locale.US);
        System.out.println(fmtChina.format(new Date()));
        System.out.println(fmtUS.format(new Date()));
        System.out.println(new SimpleDateFormat().format(new Date()));
输出:
星期四
Thu
17-3-16 上午9:30
这里没什么好说的,以下重点讲一下字母模板。

字母模板
SimpleDateFormat使用一个字符串表示日期格式化和字符串解析的规则。就是我们之前常用的new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")。其中y表示年,M表示月,d表示日,注意的是,这里是区分大小写的,很多情况下,大小写的表示的意义是不同的。像y,M,d这些字母,被称之为字母模板( pattern letters )。
详细列表:
字母
日期或时间元素
类别
示例
G
Era 标志符
Text
AD
Y
weekYear
Year
2009,09
y
Year
1996; 96
M
年中的月份
Month
July; Jul; 07
w
一年的第几周
Number
27
W
一个月的第几周(weekYear算法)
Number
2
D
一年中第几天
Number
189
d
月份中的几日
Number
10
F
一个月中第几个七天
Number
2
E
星期几
Text
Tuesday; Tue
a
Am/pm 标记
Text
PM
H
一天中的小时数(0-23)
Number
0
k
一天中的小时数(1-24)
Number
24
K
am/pm 中的小时数(0-11)
Number
0
h
am/pm 中的小时数(1-12)
Number
12
m
分钟
Number
30
s
Number
55
S
毫秒
Number
978
z
时区
General time zone
Pacific Standard Time; PST; GMT-08:00
Z
时区
RFC 822 time zone
-0800

字母模板被划分了多种类型:
Text:对于格式化来说,如果字母模板的数量大于等于4,则使用完全形式;否则,在可用的情况下使用短形式或缩写形式。对于解析来说,两种形式都是可接受的,与模式字母的数量无关。比如星期几,在美国的语言环境下,在一个E下简写成Sun,四个,全写为Sunday,在中文模式下嘛,都是星期日~
Number:对于格式化来说,模式字母的数量表示至少有几位,如果数位不够,则用 0 填充以达到此数量。对于解析来说,模式字母的数量被忽略,除非必须分开两个相邻字段。
Year:yy就是两个数字来格式化,其他则全写。解析的时候同理,yy特殊解析,在解析缩写年份模式("y" 或 "yy")时,SimpleDateFormat 必须相对于某个世纪来解释缩写的年份。这通过将日期调整为 SimpleDateFormat 实例创建之前的 80 年和之后 20 年范围内来完成。例如,在 "MM/dd/yy" 模式下,如果 SimpleDateFormat 实例是在 1997 年 1 月 1 日创建的,则字符串 "01/11/12" 将被解释为 2012 年 1 月 11 日,而字符串 "05/04/64" 将被解释为 1964 年 5 月 4 日。在解析时,只有恰好由两位数字组成的字符串(如 Character.isDigit(char) 所定义的)被解析为默认的世纪。其他任何数字字符串将照字面意义进行解释,例如单数字字符串,3 个或更多数字组成的字符串,或者不都是数字的两位数字字符串(例如"-1")。因此,在相同的模式下, "01/02/3" 或 "01/02/003" 解释为公元 3 年 1 月 2 日。同样,"01/02/-3" 解析为公元前 4 年 1 月 2 日。这里说的是高里历,其他历法,我也不知道~
Month: 如果模式字母的数量为 3 或大于 3,则将月份解释为 text;否则解释为 number。
置于时区,我懒得想了~╮(╯▽╰)╭

举个栗子:
         SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.SIMPLIFIED_CHINESE);

         Calendar cld = Calendar.getInstance();
         cld.set(2017, Calendar.MARCH, 14, 12, 0, 0);
         cld.clear(Calendar.MILLISECOND);
         Date d = cld.getTime();

         String[] patterns = {"yyyy-MM-dd HH:mm:ss","G-E-a","GGGG-EEEE-aaaa",
                  "yyyy-MM-dd  HH:mm:ss:SSS,是yy年第D天,M月的第W周第FF个七天,EEEE, 时间是aaaaKK时mm分ss秒"
         };

         for(String p:patterns){
              fmt.applyPattern(p);
              System.out.println(p + ": " + fmt.format(d));
         }

输出:
yyyy-MM-dd HH:mm:ss: 2017-03-14 12:00:00
G-E-a: 公元-星期二-下午
GGGG-EEEE-aaaa: 公元-星期二-下午
yyyy-MM-dd  HH:mm:ss:SSS,是yy年中的第w周的第D天,M月的第W周第FF个七天,EEEE, 时间是aaaaKK时mm分ss秒: 2017-03-14  12:00:00:000,是17年中的第73天,3月的第3周第02个七天,星期二, 时间是下午00时00分00秒

这里值得注意的是,字母模板是大小写敏感的,大小写敏感的,大小写敏感的,敏感的!!!!!


说实话,好烦,记呢,谁记得住哇~~,用时候再翻吧~,这里举几个例子强调一下重要性!

         SimpleDateFormat fmt = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss",Locale.SIMPLIFIED_CHINESE);
         Calendar cld = Calendar.getInstance();
         cld.set(2015, Calendar.DECEMBER, 31, 0, 0, 0);
         System.out.println(fmt.format(cld.getTime()));
         cld.set(2016, Calendar.DECEMBER, 31, 0, 0, 0);
         System.out.println(fmt.format(cld.getTime()));
注意啦!!!这里格式化是用的大写的YYYY,对照上表中,可以知道,这个是weekYear,上一节中,已经讲过概念,就是每一年的第一周的第一天,算是这一年的开始。也可以说,年末的最后一周,如果不满7天,归到下一年。查一下日历,算一下结果:
2016-12-31 00:00:00
2016-12-31 00:00:00
惊不惊喜!!!!2015年12月31日和2016年12月31日居然格式化成了同一天!!!!因为这两天在weekYear中,都是2016年的,所以,就格式化成了这个鬼样子!!!

蛋是
千万不要以为这是个bug,这是我们用错啦!!!你使用weekYear,那么就没有月日的概念,你使用月日,就是常规年,不要用YYYY!!!!
我们应该这么用:

         SimpleDateFormat fmtCorrect = new SimpleDateFormat("YYYY第w周E",Locale.SIMPLIFIED_CHINESE);
         cld.set(2015, Calendar.DECEMBER, 31, 0, 0, 0);
         System.out.println(fmtCorrect.format(cld.getTime()));
         cld.set(2016, Calendar.DECEMBER, 31, 0, 0, 0);
         System.out.println(fmtCorrect.format(cld.getTime()));
这回在看结果:
2016年第1周星期四
2016年第53周星期六
使用weekYear,那么概念就是,某某年第XX周星期X,这样来表示时间的!!

既然都有weekYear的概念了,那么一周的开始时间是周几,必然需要设置,怎么设置呢。好,蛋疼的地方来了,SimpleDateFormat对象内置了一个calendar对象,通过设置calendar对象的firstDayOfWeek,来设置一周的第一天是星期几~╮(╯▽╰)╭,用起来是不是有点,蛋蛋的忧伤。

      SimpleDateFormat fmt = new SimpleDateFormat("YYYY第w周E");

      Calendar defaultCld = fmt.getCalendar();
      defaultCld.setFirstDayOfWeek(Calendar.MONDAY);

      Calendar calendar = Calendar.getInstance();
      calendar.set(2016, Calendar.DECEMBER, 31);
      Date d = calendar.getTime();

      System.out.println(fmt.format(d));
      defaultCld.setFirstDayOfWeek(Calendar.SUNDAY);
      System.out.println(fmt.format(d));
输出:
2017第1周星期六
2016第53周星期六
另外
如果格式化中有英文字符,请用单引号包围起来。

解析
解析和格式化的字母模板的定义差不多,细微的差别,以上已经讲过了,只说两个问题:
1.lenient
上一节我们讲过lenient,这里也是一样,默认的是TRUE,是宽松的,1月32日会被解析为2月1日。

          SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
          System.out.println(fmt.format(fmt.parse("2017-01-32")));
          fmt.setLenient(false);
          System.out.println(fmt.format(fmt.parse("2017-01-32")));
输出:
2017-02-01
Exception in thread bla bla bla
2.时区
相同的字符串,在不同的时区表示的意思显然是不同的!!!如果我们真的需要考虑时区问题,那么你解析的时候,必须指定时区,在SimpleDateFormat对象中。栗子之前Calendar夏令时的时候,已经有了~~

0 0
原创粉丝点击