ZoneOffset的ID无效

时间:2016-04-29 21:14:53

标签: mysql date java-8 timestamp datetimeoffset

我正在尝试从java.sql.timestamp转换为OffsetDateTime,以便我可以在其余的api中返回ISO8601标准字符串。我使用此代码将timestamp转换为OffsetDateTime

public static OffsetDateTime sqlTimetampeToOffsetDateTime(Timestamp ts, String timeZone)
{
    if (ts == null)
    {
        return null;
    }

    Calendar cal = Calendar.getInstance();
    cal.setTime(ts);
    ZoneOffset offset = ZoneOffset.of(timeZone);
    return OffsetDateTime.of(
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH)+1,
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.SECOND),
            cal.get(Calendar.MILLISECOND)*1000000,
            offset);
}

但是,代码在值ZoneOffset offset = ZoneOffset.of(timezone)的{​​{1}}处失败。

我使用以下代码打印所有时区的列表,我确实在该列表中看到Europe/Copenhagen

Europe/Copenhagen

现在我不明白发生了什么。如何将 Set<String> allZones = ZoneId.getAvailableZoneIds(); LocalDateTime dt = LocalDateTime.now(); List<String> zoneList = new ArrayList<String>(allZones); Collections.sort(zoneList); for (String s : zoneList) { ZoneId zone = ZoneId.of(s); ZonedDateTime zdt = dt.atZone(zone); ZoneOffset offset = zdt.getOffset(); int secondsOfHour = offset.getTotalSeconds() % (60 * 60); String out = String.format("%35s %10s%n", zone, offset); System.out.printf(out); } 转换为java.sql.timestamp字符串(我不在乎是否必须使用ISO8601。我不想使用任何第三方库

http://pastebin.com/eHJKWpAv

3 个答案:

答案 0 :(得分:3)

ZoneOffset仅在处理特定时间点时才有意义。在欧洲/伦敦,我们目前使用BST或GMT,具体取决于一年中的时间。然而,100年前(给予或接受),欧洲/伦敦没有BST。 ZoneOffset.of()仅从内部缓存中检索区域偏移,该缓存仅在调用ZoneOffset.ofTotalSeconds()时填充。记录很少。但是,存在一个简单的解决方案:

ZoneId.of("Europe/London").getRules().getOffset(Instant.now());

现在返回欧洲/伦敦的正确ZoneOffset(例如今天)

答案 1 :(得分:1)

如果您拥有ZoneId,使用Instant类执行此操作非常简单:

Timestamp t = new Timestamp(System.currentTimeMillis());

ZoneId zone = ZoneId.of("Europe/Copenhagen");

OffsetDateTime offsetDateTime = ZonedDateTime
    .ofInstant(Instant.ofEpochMilli(t.getTime()), zone)
    .toOffsetDateTime();

答案 2 :(得分:-1)

我确实设法转换它,但我不确定这是否是正确的方法。这是我正在寻找答案的其他人的代码

#navbar
{
    clear:both;
    overflow:hidden;
    background-color: #006633;
    font-size: 11pt;
    height: 1.75em;
}

#navbarItems
{
    list-style-type: none;
    margin: 0;
    padding: 0;
    float: right;
}

.navbarItem
{
    display: block;
    float: left;
    padding: 0;
    margin: 0;
}

.navbarItemLink
{
    display:block;
    color: #ffffff;
    text-decoration: none;
    text-align: center;
    padding: 0.25em;
    font-size: 11pt;
}

其中<div id="navbar"> <ul id="navbarItems"> <li class="navbarItem"><a href="editAccount.aspx" class="navbarItemLink">ACCOUNT</a></li> <li class="navbarItem"><a href="Logout.aspx" class="navbarItemLink">LOGOUT</a></li> </ul> </div> 的格式为public static OffsetDateTime sqlTimetampeToOffsetDateTime(Timestamp ts, String timeZone) { if (ts == null) { return null; } ZoneId zoneId = ZoneId.of(timeZone); Calendar cal = Calendar.getInstance(); cal.setTime(ts); ZonedDateTime zdt = ZonedDateTime.of( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND) * 1000000, zoneId); return zdt.toOffsetDateTime(); } ...您可以在问题中发布的我的pastebin网址中看到timeZone支持的完整列表