ZonedDateTime 格式,用于显示当前时间,并已包含偏移量

ZonedDateTime format to display current time with offset already included

提问人:paul590 提问时间:3/25/2017 最后编辑:Arvind Kumar Avinashpaul590 更新时间:8/19/2020 访问量:3123

问:

我一直在寻找这个答案,但我可能误会如何实现它。我有一个 ZonedDateTime 变量,目前如果我要打印它,它会打印例如 2017-12-03T10:15:30+01:00。有没有办法在已经添加或减去偏移量的情况下打印时间?例如,我想看看上面的示例 16:30。谢谢你的帮助!

android java-time zoneddatetime threetenbp

评论

2赞 korolar 3/25/2017
如果我理解正确的话,您要做的事情相当于在 UTC 中显示 ZonedDateTime 实例。您可以在 DateTimeFormatter 上设置时区,因此只需这样做即可。
1赞 Andreas 3/25/2017
2017-12-03T10:15:30+01:00是给定时区中的时间,或 UTC 时区(不是 )。时间已在给定时区。如果要删除偏移量信息,请调用 toLocalDateTime() 获取 .反对票,因为这个问题是基于对 ISO 日期格式的误解。10:15:3009:15:3016:302017-12-03T10:15:30
0赞 paul590 3/25/2017
谢谢你的帮助!我解决了我的问题!

答:

2赞 Andre Alexandre 3/25/2017 #1

看看这个:

    public Date parseDateTime(String input) throws java.text.ParseException {

    //NOTE: SimpleDateFormat uses GMT[-+]hh:mm for the TZ which breaks
    //things a bit.  Before we go on we have to repair this.
    SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );

    //this is zero time so we need to add that TZ indicator for
    if ( input.endsWith( "Z" ) ) {
        input = input.substring( 0, input.length() - 1) + "GMT-00:00";
    } else {
        int inset = 6;

        String s0 = input.substring( 0, input.length() - inset );
        String s1 = input.substring( input.length() - inset, input.length() );

        input = s0 + "GMT" + s1;
    }

    return df.parse( input );
}

只需进行一些更改,即可满足您的需求。你应该能够毫不费力地做到这一点。然后,在拥有 Date 对象后,添加所需的偏移量:

int myNumHours = 4; //Any number of hours you want
myDateObject.add(Calendar.HOUR,myNumHours); 
//Adds myNumHours to the Hour slot and processes all carrys if needed be.

现在要打印它:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String myDateString = df.format(myDateObject);
//Now just use your myDateString wherever you want.
2赞 Demigod 8/18/2020 #2

TL的;博士

yourZonedDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault())

或者就我而言:

serverSeconds.toLocalDateTime(ZonedDateTime.now().offset)   // extension below

fun Long.toLocalDateTime(zoneOffset: ZoneOffset = ZoneOffset.UTC): LocalDateTime {
    return LocalDateTime.ofEpochSecond(this / 1000L, 0, zoneOffset)
}

历史

当我尝试正确格式化从服务器收到的日期时间时,我偶然发现了这个问题。我做了这些简单的步骤:

  • 服务器给了我这个:,这是一个以秒为单位的日期时间。1597752329121
  • 将其转换为 LocalDateTime 后,我得到了这个: .2020-08-18T12:05:29
  • 将其转换为 ZonedDateTime 给了我这个:2020-08-18T12:05:29+03:00[Europe/Kiev]

这很完美,因为我需要像这样显示它,简单吧?但是以任何方式格式化它都是嘲弄地给了我.太傻了。我开始搜索我做错了什么,只找到“聪明”的评论,比如“时间已经在给定的时区了”,你应该只得到它。15:05, 18 August 202012:05, 18 August 2020

comment

但是,如果 ZonedDateTime 以任何方式为您提供 12:05 而不是 15:05,那怎么可能呢?!

无论如何,我终于找到了这个答案(https://stackoverflow.com/a/35689566/3569545),实际上,它并没有解决我的问题,但给出了一些关于如何解决它的想法。所以最后我尝试了这个:

val localDate = serverSeconds.toLocalDateTime()    //an extension, see below
val zonedUTC = localDate.atZone(ZoneOffset.UTC)
val zoned = zonedUTC.withZoneSameInstant(ZoneId.systemDefault())

fun Long.toLocalDateTime(): LocalDateTime {
    return LocalDateTime.ofEpochSecond(this / 1000L, 0, ZoneOffset.UTC)
}

最后格式化给了我所需的. 我将其改进为代码,您可以在上面的tl中看到;博士zoned15:05, 18 August 2020

1赞 Arvind Kumar Avinash 8/19/2020 #3

ZonedDateTime#withZoneSameInstant

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateTimeStr = "2017-12-03T10:15:30+01:00";
        ZonedDateTime zdtGiven = ZonedDateTime.parse(dateTimeStr);
        System.out.println(zdtGiven);

        // Date-time adjusted with Zone-Offset (i.e. date-time at UTC)
        ZonedDateTime zdtAtUTC = zdtGiven.withZoneSameInstant(ZoneId.of("Etc/UTC"));
        System.out.println(zdtAtUTC);

        // Alternatively,
        OffsetDateTime odtAtUTC = zdtGiven.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println(odtAtUTC);

        // Custom format
        String formattedDateTimeStr = zdtAtUTC.format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss"));
        System.out.println(formattedDateTimeStr);
    }
}

输出:

2017-12-03T10:15:30+01:00
2017-12-03T09:15:30Z[Etc/UTC]
2017-12-03T09:15:30Z
2017-12-03T09:15:30

你理解的差距:

日期时间字符串中的日期和时间表示字符串中的日期和时间已经通过在日期和时间中添加小时来调整。这意味着如果你想从中删除,需要从中减去小时,即它将成为代表日期和时间。+01:002017-12-03T10:15:30+01:00+01:00UTC+01:00+01:002017-12-03T10:15:302017-12-03T09:15:30UTC