Java日历设置时区方法行为

Java日历设置时区方法行为,java,calendar,timezone,Java,Calendar,Timezone,当我使用java6在windows上运行下面的代码时,它会打印以下输出 private static SimpleDateFormat timeZoneFormatter = new SimpleDateFormat("Z"); public static void main(String[] args) { try { String format = "yyyyMMdd"; SimpleDateFormat dateFormat = new Simpl

当我使用java6在windows上运行下面的代码时,它会打印以下输出

private static SimpleDateFormat timeZoneFormatter = new SimpleDateFormat("Z");
public static void main(String[] args) {
    try {
        String format = "yyyyMMdd";

        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        Date date1 = dateFormat.parse("20140330");
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);

        Date date2 = dateFormat.parse("20140401");

        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        calendar1.setTimeZone(TimeZone.getTimeZone("GMT"));
        calendar2.setTimeZone(TimeZone.getTimeZone("GMT"));

        System.out.println(timeZoneFormatter.format(calendar1.getTime()));
        System.out.println(timeZoneFormatter.format(calendar2.getTime()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
+0200
+0300

就我所见,无论我在calendar对象上设置了什么时区,它都会在SimpleDataFormat对象上使用defaulttimezone信息。我是不是遗漏了什么?如果这是正常行为,在哪种情况下我们应该使用Calendar.setTimezone()方法

在您的示例中,时区设置无效的原因是:而不是应用
setTimeZone
对于日历对象,应将
setTimeZone
应用于
timeZoneFormatter
对象

请参见下面我的可执行示例代码。此代码将演示时区的用法和效果。

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class TimeZoneTEST {
    private static SimpleDateFormat timeZoneFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
    public static void main(String[] args) {
        try {
            String timezone_GMT = "GMT";
            String timezone_NYC = "America/New_York";
            long currentLongTime = System.currentTimeMillis();

            // Effect of time zone when displaying time as hhmm
            System.out.format("Current time(HHMM) in [%s] time zone is [%d]\n", timezone_GMT, getCurrentTime(currentLongTime, timezone_GMT));
            System.out.format("Current time(HHMM) in [%s] time zone is [%d]\n", timezone_NYC, getCurrentTime(currentLongTime, timezone_NYC));

            // Effect of time zone when displaying the formatted string representation of time
            System.out.format("Current time(String representation) in [%s] time zone is [%s]\n", timezone_GMT, fmtDateWithTZ(currentLongTime,timezone_GMT));
            System.out.format("Current time(String representation) in [%s] time zone is [%s]\n", timezone_NYC, fmtDateWithTZ(currentLongTime,timezone_NYC));
            } catch (Exception e) {
        }
    }

    public static int getCurrentTime(long longTime, String timeZone){
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
        cal.setTimeInMillis(longTime);
        int hhmm = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE);
        return hhmm;    
    }

    public static String fmtDateWithTZ( long ms, String timeZone) {
        timeZoneFormatter.setTimeZone(TimeZone.getTimeZone(timeZone));
        return timeZoneFormatter.format( new Date( ms) );
    } 
}
运行代码后,应看到以下输出(显示的实际时间为当前时间):

[GMT]时区中的当前时间(HHMM)为[945]

[美国/纽约]时区的当前时间(HHMM)为[545]

[GMT]时区中的当前时间(字符串表示法)为[2014-09-09:45:42 GMT]

[美国/纽约]时区的当前时间(字符串表示法)为[2014-09-09 05:45:42美国东部夏令时]


侧注通过应用不同的时区,可以根据指定的时区以不同方式显示相同的时间成分。这与时间的长时间表示法不同,长时间表示法测量自1970年1月1日午夜以来经过的毫秒数。此数量是时区中性的,其值不会随时区变化。

在您的示例中,时区设置无效的原因是:而不是应用
setTimeZone
对于日历对象,应将
setTimeZone
应用于
timeZoneFormatter
对象

请参见下面我的可执行示例代码。此代码将演示时区的用法和效果。

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class TimeZoneTEST {
    private static SimpleDateFormat timeZoneFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
    public static void main(String[] args) {
        try {
            String timezone_GMT = "GMT";
            String timezone_NYC = "America/New_York";
            long currentLongTime = System.currentTimeMillis();

            // Effect of time zone when displaying time as hhmm
            System.out.format("Current time(HHMM) in [%s] time zone is [%d]\n", timezone_GMT, getCurrentTime(currentLongTime, timezone_GMT));
            System.out.format("Current time(HHMM) in [%s] time zone is [%d]\n", timezone_NYC, getCurrentTime(currentLongTime, timezone_NYC));

            // Effect of time zone when displaying the formatted string representation of time
            System.out.format("Current time(String representation) in [%s] time zone is [%s]\n", timezone_GMT, fmtDateWithTZ(currentLongTime,timezone_GMT));
            System.out.format("Current time(String representation) in [%s] time zone is [%s]\n", timezone_NYC, fmtDateWithTZ(currentLongTime,timezone_NYC));
            } catch (Exception e) {
        }
    }

    public static int getCurrentTime(long longTime, String timeZone){
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
        cal.setTimeInMillis(longTime);
        int hhmm = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE);
        return hhmm;    
    }

    public static String fmtDateWithTZ( long ms, String timeZone) {
        timeZoneFormatter.setTimeZone(TimeZone.getTimeZone(timeZone));
        return timeZoneFormatter.format( new Date( ms) );
    } 
}
运行代码后,应看到以下输出(显示的实际时间为当前时间):

[GMT]时区中的当前时间(HHMM)为[945]

[美国/纽约]时区的当前时间(HHMM)为[545]

[GMT]时区中的当前时间(字符串表示法)为[2014-09-09:45:42 GMT]

[美国/纽约]时区的当前时间(字符串表示法)为[2014-09-09 05:45:42美国东部夏令时]


侧注通过应用不同的时区,可以根据指定的时区以不同方式显示相同的时间成分。这与时间的长时间表示法不同,长时间表示法测量自1970年1月1日午夜以来经过的毫秒数。此数量与时区无关,其值不会随时区而更改。

在您的示例中,timeZoneFormatter不是格式化calendar1的时区,而是格式化calendar1.getTime()返回的匿名日期的时区。正在格式化的就是这个日期对象。由于日期没有时区,因此它是根据格式化程序的时区进行格式化的,在本例中,该时区是默认时区。

在您的示例中,timeZoneFormatter不是格式化calendar1的时区,而是格式化calendar1.getTime()返回的匿名日期的时区。正在格式化的就是这个日期对象。由于日期没有时区,因此它是根据格式化程序的时区进行格式化的,在本例中,该时区是默认时区。

谢谢您的评论。实际上,格式化程序部分来自api(我不能更改它),我应该发送一个日历对象。我正在想办法设置时区。谢谢你的评论。实际上,格式化程序部分来自api(我不能更改它),我应该发送一个日历对象。我在想办法设定时区。