从ISO 8601日期字符串转换为BigQuery时间戳时出错

问题描述 投票:0回答:4

我有一个ISO 8601日期字符串,格式如下:

String myIsoDateString = "2019-02-27T23:00:00.000Z"

我需要使用日期字符串作为我在BigQuery中运行的查询的一部分。我正在尝试使用com.google.cloud.bigquery.QueryParameterValue类将其转换为QueryParameterValue,其类型为timestamp,如下所示:

QueryParameterValue.timestamp(myIsoDateString)

这给了我一个错误:

java.lang.IllegalArgumentException: Invalid format: "2019-02-27T23:00:00.000Z" is malformed at "T23:00:00.000Z"

Eclipse中对timestamp方法的内联帮助声明:

Creates a QueryParameterValue object with a type of TIMESTAMP. Must be in the format"yyyy-MM-dd HH:mm:ss.SSSSSSZZ", e.g. "2014-08-19 12:41:35.220000+00:00".

如何将myIsoDateString转换为所需格式?有没有更好的方法可以处理从ISO 8601字符串转换为BigQuery中的时间戳?

java date datetime google-bigquery iso8601
4个回答
3
投票

我希望得到Felipe Hoffa的答案能够解决你想要的问题:用空格替换T。以下是其他一些建议。

明确:虽然文档提供了一个非常明确的预期字符串示例,但是从错误消息或文档(下面的链接,但你已经在Eclipse中得到它)中不清楚QueryParameterValue.timestamp是否接受Z作为偏移量。如果我们想要确定并且更明确地提供所要求的格式(对于那些管理代码的人总是很好):

    DateTimeFormatter timestampFormatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSSxxx");
    String myIsoDateString = "2019-02-27T23:00:00.000Z";
    OffsetDateTime dateTime = OffsetDateTime.parse(myIsoDateString);
    QueryParameterValue.timestamp(dateTime.format(timestampFormatter));

这将字符串2019-02-27 23:00:00.000000+00:00传递给timestamp

通过一个长期:timestamp进入一个重载版本采取Long论点。同样,没有记录长值应该是什么。编辑:你自己的答案显示,timestamp(Long)需要自纪元以来的微秒。完全正确的转换方式,没有任何不必要的精度损失的风险是:

    String myIsoDateString = "2019-02-27T23:00:00.000Z";
    Instant dateTime = Instant.parse(myIsoDateString);
    long microsecondsSinceEpoch = TimeUnit.SECONDS.toMicros(dateTime.getEpochSecond())
            + TimeUnit.NANOSECONDS.toMicros(dateTime.getNano());
    QueryParameterValue.timestamp(microsecondsSinceEpoch);

价值1 551 308 400 000 000被传递给timestamp

免责声明:我不是BigQuery用户。

链接


1
投票

ISO 8601 versus SQL

ISO 8601标准在中间使用T将年 - 月 - 日部分与小时 - 分 - 秒部分分开。

SQL风格在中间使用SPACE而不是T

更换。

String input = "2019-02-27T23:00:00.000Z".replace( "T" , " " ) ;
QueryParameterValue.timestamp( input ) ;

同样朝着另一个方向前进。在解析/生成文本时,java.time类在默认情况下使用ISO 8601格式。

String input = "2019-02-27 23:00:00.000Z".replace( " " , "T" ) ;
Instant instant = Instant.parse( input ) ;
ZonedDateTime zdt = instant.atZone( ZoneId.of( "Pacific/Auckland" ) ) ;

1
投票

错误说这不是正确的格式:

 "2019-02-27T23:00:00.000Z"

但这个会是:

 "yyyy-MM-dd HH:mm:ss.SSSSSSZZ"

尝试用T替换日期和时间之间的


0
投票

这有效:

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

myIsoDateString转换为微秒并将其存储为long

long myDateInMicroseconds = DateTime.parse(myIsoDateString).toDateTime(DateTimeZone.UTC).getMillis() * 1000;

然后将它作为参数传递给QueryParameterValue.timestamp:

QueryParameterValue.timestamp(myDateInMicroseconds)

0
投票

对于那些只是想在BigQuery中解析ISO 8601的人(这篇文章是Google的第一个结果),试试这个:

SELECT
PARSE_TIMESTAMP('%Y-%m-%dT%H:%M:%E*SZ',  '2018-10-12T13:22:27.120Z')
© www.soinside.com 2019 - 2024. All rights reserved.