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

时间:2019-03-14 03:31:27

标签: java date datetime google-bigquery iso8601

我有一个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中的时间戳的转换吗?

5 个答案:

答案 0 :(得分: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 :(得分:1)

该错误表明这不是正确的格式:

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

但这是:

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

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

答案 2 :(得分:1)

ISO 8601与SQL

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

SQL样式在中间使用空格,而不是T

替换。

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

Ditto用于其他方向。解析/生成文本时, 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" ) ) ;

答案 3 :(得分: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)

答案 4 :(得分:0)

对于任何试图在BigQuery中解析ISO 8601的人(这篇文章是Google的第一个结果),请尝试以下操作:

SELECT
PARSE_TIMESTAMP('%Y-%m-%dT%H:%M:%E*SZ',  '2018-10-12T13:22:27.120Z')