java中的Date和时区

Date本身没有时区概念

查看源码可以知道, Date对象中存储的是一个long型变量
这个变量的值为自1997-01-01 00:00:00(GMT)至Date对象记录时刻所经过的毫秒数
可以通过getTime()方法,获取这个变量值,且这个变量值和时区没有关系
全球任意地点同时执行new Date().getTime()获取到的值相同

Date源码

	private transient long fastTime;
    
    /**
     * Allocates a <code>Date</code> object and initializes it so that
     * it represents the time at which it was allocated, measured to the
     * nearest millisecond.
     *
     * @see     java.lang.System#currentTimeMillis()
     */
    public Date() {
        this(System.currentTimeMillis());
    }

    /**
     * Allocates a <code>Date</code> object and initializes it to
     * represent the specified number of milliseconds since the
     * standard base time known as "the epoch", namely January 1,
     * 1970, 00:00:00 GMT.
     *
     * @param   date   the milliseconds since January 1, 1970, 00:00:00 GMT.
     * @see     java.lang.System#currentTimeMillis()
     */
    public Date(long date) {
        fastTime = date;
    }

    /**
     * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
     * represented by this <tt>Date</tt> object.
     *
     * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
     *          represented by this date.
     */
    public long getTime() {
        return getTimeImpl();
    }

    private final long getTimeImpl() {
        if (cdate != null && !cdate.isNormalized()) {
            normalize();
        }
        return fastTime;
    }
	
	    /**
     * Converts this <code>Date</code> object to a <code>String</code>
     * of the form:
     * <blockquote><pre>
     * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
     * where:<ul>
     * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
     *     Thu, Fri, Sat</tt>).
     * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
     *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
     * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
     *     <tt>31</tt>), as two decimal digits.
     * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
     *     <tt>23</tt>), as two decimal digits.
     * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
     *     <tt>59</tt>), as two decimal digits.
     * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
     *     <tt>61</tt>, as two decimal digits.
     * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving
     *     time). Standard time zone abbreviations include those
     *     recognized by the method <tt>parse</tt>. If time zone
     *     information is not available, then <tt>zzz</tt> is empty -
     *     that is, it consists of no characters at all.
     * <li><tt>yyyy</tt> is the year, as four decimal digits.
     * </ul>
     *
     * @return  a string representation of this date.
     * @see     java.util.Date#toLocaleString()
     * @see     java.util.Date#toGMTString()
     */
    public String toString() {
        // "EEE MMM dd HH:mm:ss zzz yyyy";
        BaseCalendar.Date date = normalize();
        StringBuilder sb = new StringBuilder(28);
        int index = date.getDayOfWeek();
        if (index == BaseCalendar.SUNDAY) {
            index = 8;
        }
        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd

        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
        // 注意: 这里涉及到时区
        TimeZone zi = date.getZone();
        if (zi != null) {
            sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
        } else {
            sb.append("GMT");
        }
        sb.append(' ').append(date.getYear());  // yyyy
        return sb.toString();
    }

getTime()获取毫秒数,获取到的毫秒数和格式化后时间的关系

这个变量的值为自1997-01-01 00:00:00(GMT)至Date对象记录时刻所经过的毫秒数
这个毫秒数和格式化后时间是模型和视图的关系, 时区(TimeZone)决定了同一模型展示成什么样的视图(格式化Date)

	Date date = new Date();
	System.out.println(date);
	System.out.println(date.getTime());

	// 输出
	Tue Dec 10 18:44:24 CST 2019
	1575974664352

格式化Date对象成字符串, 涉及时区

不管是调用Date对象的toString方法, 还是使用SimpleDateFormat的format方法去格式化Date对象,或者使用parse解析字符串成Date对象都会涉及到时区,
也就是说Date对象没有时区概念, 但是格式化Date对象, 或者解析字符串成Date对象时, 是有时区概念的

toString

	Date date = new Date();
	// 默认是系统时区
	System.out.println(date);
	// 修改默认时区
	TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
	System.out.println(date);

	// 输出
	Tue Dec 10 19:03:46 CST 2019
	Tue Dec 10 11:03:46 GMT 2019

SimpleDateFormat

	Date date = new Date();
	// 默认是系统时区
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	System.out.println(dateFormat.format(date));
	// 设置时区
	dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+1:00"));
	System.out.println(dateFormat.format(date));

	// 输出
	2019-12-10 19:06:31
	2019-12-10 12:06:31

解析字符串成Date对象, 涉及时区

将同一个时间字符串按照不同的时区来解析, 得到的Date对象值不一样
很好理解: 东八区8点当然和0时区8点不一样

	String dateStr = "2019-12-10 08:00:00";
    // 默认是系统时区
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date1 = dateFormat.parse(dateStr);
    System.out.println(date1.getTime());
      
    // 设置时区
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+1:00"));
    Date date2 = dateFormat.parse(dateStr);
    System.out.println(date2.getTime());

	// 输出
	1575936000000
	1575961200000

将本地的时间字符串转换成另一时区的时间字符串

	String dateStr = "2019-12-10 08:00:00";
	// 按照本地时区解析字符串成Date
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date1 = dateFormat.parse(dateStr);
    // 使用目标时区格式化Date
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+9:00"));
    System.out.println(dateFormat.format(date1));

	// 输出
	2019-12-10 09:00:00
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值