Java_日期时间上(13)

约定

格林威治时间 GMT 和世界标准时间 UTC 基本相同,中国位于东八区,比格林威治时间早 8 个小时,所以使用 GMT + 8 表示中国时间,CST 表示北京时间,CST = GMT + 8

UNIX 时间戳 timestamp 是以 GMT 时间 1970-01-01T00:00:00 为起点到现在时间的总秒数,Java 遵循了这一约定

java.util 包

Date

Integer 占 32 位,能表示的最大值 MAX_VALUE = 2147483647,所以最长只能表示 68 年

Date 对象表示一个精确到毫秒的时间,有提供获取和设置年、月、日、时、分、秒的方法,也允许格式化和解析日期字符串

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Test {
  public static void main(String[] args) {
    Date d1 = new Date();
    System.out.println(d1); //Sun Jun 09 16:02:25 CST 2019
    System.out.println(d1.getTime()); //1560067345320
    System.out.println(System.currentTimeMillis()); //1560067345376
    d1.setTime(1000); //设置毫秒值,改变时间对象
    System.out.println(d1); //Thu Jan 01 08:00:01 CST 1970
    Date d2 = new Date(0); //通过毫秒值创建时间对象
    System.out.println(d2); //Thu Jan 01 08:00:00 CST 1970
    //应该是0点,但是电脑设置了东8区,所以打印8点
  }
}

JDK 1.0 承载日期时间信息,提供日期时间转换,提供不同日期格式显示,都由 Date 负责

JDK 1.1 之后,由 Calendar 提供日期时间转换,DateFormat 提供不同日期格式显示,Date 只用承载日期时间信息,其他方法已被废弃

Calendar

Date 和 Calendar 相互转换

1
2
3
4
5
6
7
8
public class Test {
  public static void main(String[] args) {
    Date date = new Date();
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);    //Date转换为Calendar
    date = cal.getTime(); //Calendar换为Date
  }
}

Calendar 是抽象类,采用了工厂方法模式,根据传入的参数返回对应的 Calendar 对象,例如调用 Calendar.getInstance 方法默认返回其子类 GregorianCalendar 的对象,其中提供了大多数国家地区使用的标准日历,可以通过传入参数 Calendar.getInstance(TimeZone timezone, Locale locale) 来获取对应时区 zone 或地区 local 使用的标准日历

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class Test {
  public static void main(String[] args) {
    //显式美国洛杉矶时区
    Calendar cal = Calendar
      .getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
    //通过System.out.println输出时间,会调用Date类的toString方法
    //而Date类的toString显式的是操作系统的默认时区
    //传入了参数但是并没有将默认时区设置成传入的时区
    System.out.println(cal.getTime()); //Sun Jun 09 18:01:34 CST 2019
    //改变了默认时区就能显式美国洛杉矶时间
    TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
    System.out.println(cal.getTime()); //Sun Jun 09 03:01:34 PDT 2019
  }
}

Calendar 提供了日期时间转换 API

 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
public class Test {
  public static void main(String[] args) {
    Calendar c = Calendar.getInstance();
    System.out.println(c.get(Calendar.YEAR));
    System.out.println(c.get(Calendar.MONTH ) + 1);  //+1是因为月是以0开始编号
    System.out.println(c.get(Calendar.DAY_OF_MONTH));
    System.out.println(c.get(Calendar.DAY_OF_WEEK)); //周日是第一天
    System.out.println(c.get(Calendar.DAY_OF_WEEK_IN_MONTH));
    System.out.println(c.get(Calendar.DAY_OF_YEAR));
    //2019年06月09日星期六
    System.out.println(c.get(Calendar.YEAR) + "年" + getNum((c.get(Calendar.MONTH) + 1)) + "月" + getNum(c.get(Calendar.DAY_OF_MONTH)) + "日" + getWeek(Calendar.DAY_OF_WEEK));

    //修改日期
    c.add(Calendar.YEAR, -1); //倒退1年
    c.add(Calendar.MONTH, -5); //倒退5个月
    c.set(Calendar.YEAR, 2000); //修改年份为2000
    c.set(2000, 8, 8); //依次修改年月日,月从0开始
    //2000年09月08日星期六
    System.out.println(c.get(Calendar.YEAR) + "年" + getNum((c.get(Calendar.MONTH) + 1)) + "月" + getNum(c.get(Calendar.DAY_OF_MONTH)) + "日" + getWeek(Calendar.DAY_OF_WEEK));
  }

  //week为1 ~ 7,所以arr第一个元素没用
  public static String getWeek(int week) {
    String[] arr = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
    return arr[week];
  }
  //设置日月的0占位
  public static String getNum(int week) {
    return week > 9 ? "" + week : "0" + week;
  }
}

Calendar 定义了 time 来保存 Date 承载的时间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
protected long time;
public final void setTime(Date date) {
  setTimeInMillis(date.getTime());
}
public final Date getTime() {
  return new Date(getTimeInMillis());
}
public long getTimeInMillis() {
  if (!isTimeSet) {
    updateTime();
  }
  return time;
}

Calendar 定义了年、月、日、星期、时、分、秒等信息的 17 个字段来提供日期时间转换

 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
protected int fields[];
//Calendar的构造函数,被其子类的构造函数调用
protected Calendar(TimeZone zone, Locale aLocale) {
  fields = new int[FIELD_COUNT];
  isSet = new boolean[FIELD_COUNT];
  stamp = new int[FIELD_COUNT];
  this.zone = zone;
  setWeekCountData(aLocale);
}

public int get(int field) {
  //计算各个字段的值
  complete();
  //返回field字段的值
  return internalGet(field);
}

protected void complete() {
  if (!isTimeSet) {
    updateTime();
  }
  if (!areFieldsSet || !areAllFieldsSet) {
    computeFields(); // fills in unset fields
    areAllFieldsSet = areFieldsSet = true;
  }
}

private void updateTime() {
  //computeTime()是抽象方法,需要在Calendar的子类中定义
  computeTime();
  // The areFieldsSet and areAllFieldsSet values are no longer
  // controlled here (as of 1.5).
  isTimeSet = true;
}

protected final int internalGet(int field) {
  //实际上返回的是field数组中的第field个元素
  return fields[field];
}

DateFormat

DateFormat 是抽象类,通过 getDateInstance()、getTimeInstance()、getDateTimeInstance() 等方式获取的 DateFormat 实例对象,实际上返回的是其子类 SimpleDateFormat 的对象

DateFormat 支持的格式化风格有 FULL、LONG、MEDIUM、SHORT 长度递减

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Test {
  public static void main(String[] args) {
    Date date = new Date();
    DateFormat shortFormat  = DateFormat.getTimeInstance(DateFormat.SHORT);
    DateFormat mediumFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);
    DateFormat LONGFormat = DateFormat.getTimeInstance(DateFormat.LONG);
    DateFormat FULLFormat = DateFormat.getTimeInstance(DateFormat.FULL);
    System.out.println(shortFormat.format(date));  //下午8:35
    System.out.println(mediumFormat.format(date)); //20:35:42
    System.out.println(LONGFormat.format(date));   //下午08时35分42秒
    System.out.println(FULLFormat.format(date));   //下午08时35分42秒 CST
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Test {
  public static void main(String[] args) {
    Date date = new Date();
    DateFormat shortFormat  = DateFormat.getDateInstance(DateFormat.SHORT);
    DateFormat mediumFormat = DateFormat.getDateInstance(DateFormat.MEDIUM);
    DateFormat LONGFormat = DateFormat.getDateInstance(DateFormat.LONG);
    DateFormat FULLFormat = DateFormat.getDateInstance(DateFormat.FULL);
    System.out.println(shortFormat.format(date));  //19-6-9
    System.out.println(mediumFormat.format(date)); //2019-6-9
    System.out.println(LONGFormat.format(date));   //2019年6月9日
    System.out.println(FULLFormat.format(date));   //2019年6月9日 星期日
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Test {
  public static void main(String[] args) {
    Date date = new Date();
    DateFormat shortFormat1  = DateFormat
      .getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    System.out.println(shortFormat1.format(date)); //19-6-9 下午8:41

    //getInstance()默认getDateTimeInstance(SHORT, SHORT)
    DateFormat shortFormat2  = DateFormat.getInstance();
    System.out.println(shortFormat2.format(date)); //19-6-9 下午8:41
  }
}

SimpleDateFormat 提供了可以自定义时间格式的 API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class Test {
  public static void main(String[] args) throws ParseException {
    Date date = new Date();
    //自定义时间格式,将日期格式转换为字符串
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    SimpleDateFormat sdf2 = new SimpleDateFormat("y/M/d  Hⓜs");
    System.out.println(sdf1.format(date)); //2019年06月09日 21:02:42
    System.out.println(sdf2.format(date)); //2019/6/9  21:2:42
    //将时间字符串转换为日期对象
    String str = "2018年10月27日 16:20:25";
    SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    Date date2 = sdf4.parse(str);
    System.out.println(date2); //Sat Oct 27 16:20:25 CST 2018
  }
}

Locale

查看 Locale 支持的全部区域

1
2
3
4
5
6
7
8
public class Test {
    public static void main(String[] args) {
        Locale[] ls = Locale.getAvailableLocales();
        for (Locale locale:ls) {
            System.out.println(locale);
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Test {
  public static void main(String[] args) {
    Date date = new Date();
    //参数为语言,地区
    Locale localeCN1 = new Locale("zh", "CN");
    Locale localeCN2 = Locale.SIMPLIFIED_CHINESE;
    Locale localeUS = new Locale("en", "US");
    String cn1 = DateFormat
      .getDateInstance(DateFormat.MEDIUM, localeCN1).format(date);
    String cn2 = DateFormat
      .getDateInstance(DateFormat.MEDIUM, localeCN2).format(date);
    String us = DateFormat
      .getDateInstance(DateFormat.MEDIUM, localeUS).format(date);
    System.out.println(cn1); //2019-6-9
    System.out.println(cn2); //2019-6-9
    System.out.println(us);  //Jun 9, 2019
  }
}

TimeZone

查看 TimeZone 支持的全部时区

1
2
3
4
5
6
7
8
public class Test {
  public static void main(String[] args) {
    String[] ids = TimeZone.getAvailableIDs();
    for (String id : ids) {
      System.out.println(id);
    }
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Test {
  public static void main(String[] args) {
    Date date = new Date();
    DateFormat df = DateFormat.getInstance();
    //默认时区
    TimeZone tz = TimeZone.getDefault();
    df.setTimeZone(tz); //设置时区为tz
    // 获取格式化后的字符串
    String str = df.format(date);
    System.out.println(tz.getID()); //Asia/Shanghai
    System.out.println(str);        //19-6-9 下午9:21
    TimeZone tz2 = TimeZone.getTimeZone("Asia/Chongqing");
    String str2 = df.format(date);
    System.out.println(tz2.getID()); //Asia/Chongqing
    System.out.println(str2);        //19-6-9 下午9:21
  }
}

以上内容是玉山整理的笔记,如有错误还请指出