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

Error when converting to BigQuery timestamp from ISO 8601 date string

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

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

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

QueryParameterValue.timestamp(myIsoDateString)

这给了我一个错误:

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

Eclipse 中时间戳方法的内联帮助指出:

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 中的时间戳的转换?

错误提示格式不正确:

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

但是这个会是:

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

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

ISO 8601 与 SQL

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

SQL 样式在中间使用 SPACE 而不是 T

替换。

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

同上去另一个方向。 java.time 类 在 parsing/generating 文本时默认使用 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" ) ) ;

我希望 Felipe Hoffa 的答案能够奏效并给你你想要的:用 space 替换 T。这里有一些其他建议。

明确: 虽然文档给出了一个非常清楚的预期字符串示例,但从错误消息和文档(下面的link,但你已经在 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

传递一个 long: timestamp 是一个带有 Long 参数的重载版本。同样,没有记录 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 用户。

链接

这个有效:

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)

任何想在 BigQuery 中解析 ISO 8601 的人(这个 post 是第一个 Google 结果),试试这个:

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