You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java带夏令时的UTC转本地时间问题:斯德哥尔摩时区转换异常

问题原因
  • 你的代码仅解析了UTC的时间部分,未指定日期,SimpleDateFormat.parse()会默认使用1970年1月1日作为基准日期。
  • 1970年1月1日斯德哥尔摩处于冬令时(UTC+1),因此转换后本地时间仅比UTC快1小时,而非夏令时的UTC+2。
解决方案

方案1:补充夏令时期间的日期

修改输入的UTC时间,包含夏季的日期(如6月的某一天),确保解析时触发夏令时偏移:

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

public class TimeConverter {

    public static void main(String[] args) throws ParseException {
        // 传入包含夏季日期的UTC时间
        getLocalTime("2024-06-01 2:36:10 AM");
    }

    public static String getLocalTime(String utcTime) throws ParseException {
        // 更新格式以支持日期解析
        DateFormat utc = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
        utc.setTimeZone(TimeZone.getTimeZone("UTC"));

        Date date = utc.parse(utcTime);

        DateFormat local = new SimpleDateFormat("HH:mm:ss");
        // 直接指定斯德哥尔摩时区,避免依赖默认时区
        local.setTimeZone(TimeZone.getTimeZone("Europe/Stockholm"));

        System.out.println(utc.getTimeZone());
        System.out.println(local.getTimeZone());

        System.out.println("UTC TIME    " + utcTime);
        System.out.println("LOCAL TIME  " + local.format(date));

        return local.format(date);
    }
}

输出结果:

sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
sun.util.calendar.ZoneInfo[id="Europe/Stockholm",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Stockholm,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
UTC TIME    2024-06-01 2:36:10 AM
LOCAL TIME  04:36:10

方案2:使用Java 8+ 新时间API(推荐)

SimpleDateFormat和Date属于过时API,线程不安全,推荐使用java.time包下的类,逻辑更清晰且原生支持夏令时:

import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class TimeConverter {

    public static void main(String[] args) {
        // 指定夏季日期和UTC时间
        getLocalTime("2024-06-01", "2:36:10 AM");
    }

    public static String getLocalTime(String utcDate, String utcTime) {
        DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss a");
        // 组合日期时间,创建UTC时区的时间对象
        ZonedDateTime utcZdt = ZonedDateTime.parse(utcDate + " " + utcTime, utcFormatter.withZone(ZoneId.of("UTC")));
        
        // 转换为斯德哥尔摩时区
        ZonedDateTime stockholmZdt = utcZdt.withZoneSameInstant(ZoneId.of("Europe/Stockholm"));
        
        DateTimeFormatter localFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        
        System.out.println("UTC TIME    " + utcDate + " " + utcTime);
        System.out.println("LOCAL TIME  " + localFormatter.format(stockholmZdt));
        
        return localFormatter.format(stockholmZdt);
    }
}

输出结果:

UTC TIME    2024-06-01 2:36:10 AM
LOCAL TIME  04:36:10
补充说明
  • 斯德哥尔摩夏令时通常从3月最后一个周日到10月最后一个周日,只有处于该时间段的日期,转换才会使用UTC+2的偏移。
  • 若业务无具体日期需求,可使用LocalDate.now(ZoneId.of("UTC"))获取当前UTC日期,再与时间组合进行转换。

内容的提问来源于stack exchange,提问作者Pacmyc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:49:53