【问题标题】:Timezone is ignored when I trying to create new broadcast当我尝试创建新广播时,时区被忽略
【发布时间】:2017-11-13 19:45:11
【问题描述】:

我正在使用 YouTube Live Streaming API。 而且我有一个问题,每次我创建直播并设置它的scheduledStartTime时,我设置的时区都会被忽略。在请求响应中,我收到 DateTime 时区为 0。

当我请求即将播出的广播列表时,我再次收到时区为-0700 的广播。 无论此广播是在哪个时区,无论请求是从哪里执行的 - 从 Android/iOS 移动客户端,或通过 YouTube API 资源管理器。

这就是我的日期格式:

String datePattern = "yyyy-MM-dd'T'HH:mm:ssZZZZZ";
DateFormat dateFormat = new SimpleDateFormat(datePattern);
dateFormat.setTimeZone(calendar.getTimeZone());

String dateFormatted = dateFormat.format(date); //2017-06-19T17:50:51+03:00

String iso8601Date = DateTime.parseRfc3339(dateFormatted);//2017-06-19T17:50:51.000+03:00

也许,问题出在我的DateTime 格式模式上。但这是 ISO 8601 日期格式表示的模式。我很困惑,为什么我的时区被忽略了?

【问题讨论】:

    标签: android datetime youtube-api timezone youtube-livestreaming-api


    【解决方案1】:

    旧的 API(带有 CalendarSimpleDateFormat 类)已经过时并且具有 lots of problems

    您应该考虑使用较新的 API。如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs

    如果您使用的是 Java ,则可以使用 ThreeTen Backport,它是 Java 8 新日期/时间类的出色反向移植。对于Android,还有ThreeTenABP(更多关于如何使用它here)。

    下面的代码适用于两者。 唯一的区别是包名(在 Java 8 中是 java.time,而在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。

    如果您正在使用包含偏移量的日期/时间,最好的选择是使用 OffsetDateTime 类,它表示带有偏移量的日期和时间。它已经有了解析String的方法:

    // parse a date string with offset -07:00
    String strDate = "2017-06-19T17:50:51.000-07:00";
    OffsetDateTime dt = OffsetDateTime.parse(strDate);
    System.out.println(dt.toString()); // 2017-06-19T17:50:51-07:00
    

    输出将是:

    2017-06-19T17:50:51-07:00

    请注意,默认情况下,toString() 方法不显示小数秒,因为它们为零。如果您想始终显示这 3 位数字,可以使用 DateTimeFormatter

    // use a formatter to always print fraction-of-second with 3 digits
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ");
    System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000-07:00
    

    在这种情况下,输出将是:

    2017-06-19T17:50:51.000-07:00

    使用不同的偏移量进行测试:

    // offset +03:00
    dt = OffsetDateTime.parse("2017-06-19T17:50:51.000+03:00");
    System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000+03:00
    // UTC: "Z" == offset zero (or "+00:00")
    dt = OffsetDateTime.parse("2017-06-19T17:50:51.000Z");
    System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000Z
    dt = OffsetDateTime.parse("2017-06-19T17:50:51.000+00:00");
    System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000Z
    

    如果您仍需使用旧 API (java.util.Calendar),您可以轻松地将其与新类相互转换。

    如果java.time 包可用,您可以这样做:

    // converting the OffsetDateTime to a Calendar
    dt = OffsetDateTime.parse("2017-06-19T17:50:51.000Z");
    Calendar c = Calendar.getInstance();
    // setting the epoch milli to calendar
    c.setTimeInMillis(dt.toInstant().toEpochMilli());
    
    // converting Calendar back to OffsetDateTime (using UTC offset)
    dt = OffsetDateTime.ofInstant(c.toInstant(), ZoneOffset.UTC);
    // converting Calendar back to OffsetDateTime (using +03:00 offset)
    dt = OffsetDateTime.ofInstant(c.toInstant(), ZoneOffset.ofHours(3));
    

    如果您使用的是 ThreeTenABP,则方法 c.toInstant() 将不可用。但是你可以使用org.threeten.bp.DateTimeUtils 类来转换它。所以,你可以使用DateTimeUtils.toInstant(c),而不是c.toInstant()

    // conversion for ThreeTenABP
    // converting Calendar back to OffsetDateTime (using UTC offset)
    dt = OffsetDateTime.ofInstant(DateTimeUtils.toInstant(c), ZoneOffset.UTC);
    // converting Calendar back to OffsetDateTime (using +03:00 offset)
    dt = OffsetDateTime.ofInstant(DateTimeUtils.toInstant(c), ZoneOffset.ofHours(3));
    

    更新:Youtube API

    我检查了Youtube API documentation(不确定您是否正在使用),在示例中它将scheduledStartTime 设置为UTC 日期/时间:

    broadcastSnippet.setScheduledStartTime(new DateTime("2024-01-30T00:00:00.000Z"));
    

    根据docs,该字段的格式如下:

    广播计划开始的日期和时间。该值以ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ) 格式指定。

    所以,我们只需要创建一个格式化程序来获取这种格式的String

    // your date/time, in -07:00 offset
    String strDate = "2017-06-19T17:50:51.000-07:00";
    OffsetDateTime odt = OffsetDateTime.parse(strDate);
    
    // formatter
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
    // convert to UTC
    String utc = formatter.format(odt.withOffsetSameInstant(ZoneOffset.UTC));
    System.out.println(utc); // 2017-06-20T00:50:51.000Z
    

    输出将采用 youtube 示例中使用的相同格式:

    2017-06-20T00:50:51.000Z

    【讨论】:

    • 谢谢你的回答,但你告诉我如何解析日期,结果我会得到格式化日期的字符串并发送到 YouTube 服务器。但是这个字符串看起来不错,问题是为什么 YouTube 会忽略我的日期?当然,我可以编辑从 YouTube 收到的日期并在上面设置我的时区,但这是一个好习惯吗?
    • 您必须检查 youtube 接受什么格式(是否有文档解释这一点?我不知道)。如果您可以提供有关它的更多详细信息,只需编辑您的问题以添加它们(如有必要,我会相应地更新我的答案)。
    • @stiletto 我已经更新了答案,看看它是否有帮助。但我不确定这是否是你需要的,所以如果你能提供更多关于你在 Youtube API 中使用的细节,那么我很乐意更新我的答案。
    • 一个好的和推荐的做法是始终在内部使用 UTC,并在需要可视化时转换到另一个时区(比如当它显示给用户时,所以你例如,在用户的时区中显示日期/时间)。但是在内部,您使用的是 UTC,因此您不会一直弄乱您的代码进行不必要的转换。这是一般规则,但当然取决于每种情况(尽管在 Youtube 的 API 中,它似乎也适用于 UTC)。
    猜你喜欢
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多