Pac*_*myc -1 java utc localtime simpledateformat
我正在尝试将 UTC 时间转换为当地时间,包括夏令时。夏季,当地时间(斯德哥尔摩)应该比 UTC 早 2 小时,但当我用 Java 转换它时,它只增加了 1 小时。
public class TimeConverter {
public static void main(String[] args) throws ParseException {
getLocalTime("2:36:10 AM");
}
public static String getLocalTime(String utcTime) throws ParseException {
DateFormat utc = new SimpleDateFormat("hh:mm:ss a");
utc.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = utc.parse(utcTime);
DateFormat local = new SimpleDateFormat("HH:mm:ss");
local.setTimeZone(TimeZone.getDefault());
System.out.println(utc.getTimeZone());
System.out.println(local.getTimeZone());
System.out.println("UTC TIME\t" + utcTime);
System.out.println("LOCAL TIME\t" + local.format(date));
return local.format(date);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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 2:36:10 AM
LOCAL TIME 03:36:10
Run Code Online (Sandbox Code Playgroud)
您的代码无意中使用了 1970 年第一天凌晨 2 点(UTC 时间)1970-01-01T02:36:10Z 的时刻。然后您调整为斯德哥尔摩时间,仍然是 1970 年,当时还没有夏令时。因此,偏移一小时 (+01:00),而不是您预期的两小时 (+02:00)。
\n请改用现代java.time类。
\nOffsetDateTime // Represent a date, a time-of-day, and an offset-from-UTC.\n .of( // Static factory method.\n LocalDate.now( ZoneOffset.UTC ) , // Date\n LocalTime.parse( "02:36:10" ) , // Time-of-day\n ZoneOffset.UTC // A constant representing an offset from UTC of zero hours-minutes-seconds.\n ) // Returns an `OffsetDateTime` object.\n .atZoneSameInstant( // Adjust to a specific time zone. Same moment, different wall-clock time/calendar.\n ZoneId.of( "Europe/Stockholm" )\n ) // Returns a `ZonedDateTime` object.\n .toString() // Returns a `String` object containing text in standard ISO 8601 format wisely extended by appending the name of the time zone in square brackets.\nRun Code Online (Sandbox Code Playgroud)\n\n\n2023-05-06T04:36:10+02:00[欧洲/斯德哥尔摩]
\n
正如预期的那样,我们看到您的 2 小时偏移量。
\n您正在使用糟糕的日期时间类,这些类现在已成为遗留的,多年前已被 JSR 310 中定义的现代java.time类取代。
\n在 UTC 中询问一天中的某个时间是没有意义的。您需要一个日期和一个时间来确定一个时刻,以表示时间轴上的一个点。
\n当以文本方式传输数据来表示时间时,请使用标准 ISO 8601 格式。对于一天中的某个时间,这仅意味着 24 小时制并填充零。
\nLocalTime lt = LocalTime.parse( "02:36:10" ) ;\nRun Code Online (Sandbox Code Playgroud)\nLocalDate&OffsetDateTime应用日期来确定时刻。也许您想要的是 UTC 中显示的当前日期。
\nLocalDate todayUtc = LocalDate.now( ZoneOffset.UTC ) ;\nOffsetDateTime odt = OffsetDateTime.of( todayUtc , lt , ZoneOffset.UTC ) ;\nRun Code Online (Sandbox Code Playgroud)\nZonedDateTime调整到时区。同一时刻,不同的挂钟时间和日历。
\nZoneId zStockholm = ZoneId.of( "Europe/Stockholm" ) ;\nZonedDateTime zdtStockholm = odt.atZoneSameInstant( zStockholm ) ;\nRun Code Online (Sandbox Code Playgroud)\n生成标准 ISO 8601 格式的文本。
\nString output = zdtStockholm.toString() ;\nRun Code Online (Sandbox Code Playgroud)\n\n\n2023-05-06T04:36:10+02:00[欧洲/斯德哥尔摩]
\n
在那里我们看到了您预期的两小时偏移。
\n您的代码失败,因为您的java.util.Date对象代表 1970 年第一天的凌晨 2 点(按 UTC 格式显示)。
避免打电话java.util.Date#toString。不幸的是,该方法在生成文本时应用了 JVM\xe2\x80\x98s 当前默认时区。这个糟糕的设计决定让事情变得更加混乱。
为了方便起见,我们将您的旧java.util.Date对象转换为其现代替代对象,java.time.Instant对象 \xe2\x80\x94 都表示与 UTC 零小时-分钟-秒的偏移量所看到的时刻。还好,Instant#toString说的是实话,不像Date#toString。
System.out.println( new SimpleDateFormat( "hh:mm:ss a" ).parse( "2:36:10 AM" ).toInstant() );\nRun Code Online (Sandbox Code Playgroud)\n\n\n1970-01-01T10:36:10Z
\n
让我们看看当时瑞典的时区规则。
\nLocalTime lt = LocalTime.parse( "02:36:10" ) ;\nRun Code Online (Sandbox Code Playgroud)\n\n\nisDst = 假
\n
因此,1970 年瑞典时区并没有实行夏令时 (DST)。
\nrules.getTransitions().toString()\nRun Code Online (Sandbox Code Playgroud)\n我们可以在该转换列表中看到 1949-10-02 和 1980-04-06 之间的偏移量为 +01:00。所以没有像你预期的那样+02:00。
\n| 归档时间: |
|
| 查看次数: |
819 次 |
| 最近记录: |