问题:为何Calendar设置timezone后,时间戳没变

 我想设置成雅加达时区(东7区,即北京时间-1h),我是这样设置时间戳的:

//我想设置成雅加达时区(东7区,即北京时间-1h)
        Date now = new Date();
        System.out.println(now);
        System.out.println(now.getTime());
        System.out.println(TimeZone.getDefault().getDisplayName());
        System.out.println("=================");

        Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("Asia/Jakarta"));
        Date date1 = cal1.getTime();
        System.out.println(date1);
        System.out.println(date1.getTime());
        System.out.println(cal1.getTimeZone().getDisplayName());
        System.out.println("=================");

        输出:
        =================
        Sun Sep 06 23:39:43 CST 2020
        1599406783471
        中国标准时间
        =================
        Sun Sep 06 23:39:43 CST 2020
        1599406783501
        西印度尼西亚时间
        =================
我惊呆了,为何设置了timezone,时间和北京时间还是一样呢??
找了网上答案,需要这样才可以达到我想要的,这是为什么呢?:
//TimeZone设置默认时区,设置一次永久生效
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Jakarta"));
        Calendar cal2 = Calendar.getInstance();
        Date date2 = cal2.getTime();
        System.out.println(date2);
        System.out.println(date2.getTime());
        System.out.println(cal2.getTimeZone().getDisplayName());

        输出:
        Sun Sep 06 22:39:43 WIB 2020
        1599406783504
        西印度尼西亚时间


        同时有个结论:date.getTime得到的时间戳几乎是一样的,只是后三位毫秒数不一样

看了网上的答案:

即:

时间和日历是两个不同的概念。
Date代表的是一个绝对时间,也就是说,不管你在哪个时区,Date都是一样的,都是从1970年1月1日0点0分GMT时间起,到目前这一刻的毫秒数。所以,你第一段代码和第二段代码里面,得到的date对象所代表的时间其实是一样的。
而日历是人们对绝对时间的一种描述方法,例如某年某月某日几时几分几秒,这,随着你当前所处的时区和地区而不同。
你在观察date对象的时候,你肯定没有去看它的毫秒数,而是先把毫秒数转换成一个日历。你没有写出你是怎么把date转换成日历的,但假如你是用默认的Date.toString()的话,那么,这是根据当前的默认时区来把毫秒数转换成日历的。因此,你在第一段代码里没有修改默认时区,得到的还是北京时间。而在第二段代码里,因为修改了默认时区,所以虽然绝对时间没有变化,但是你转换得到的日历不一样了。
其实,如果你是要获取当前时间,那么直接用new Date()就可以了,跟你先创建一个Calendar对象,再指定一个时区后获取的date是完全一样的。只有在你需要把一个date用日历来表示的时候,才需要用到Calendar和TimeZone。

 

 Date的toString(),可以看下源码

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();
    }