如何将时间戳转换为字符串(不更改时区)?

Posted

技术标签:

【中文标题】如何将时间戳转换为字符串(不更改时区)?【英文标题】:how to convert a timestamp into string (without changing timezone)? 【发布时间】:2018-08-27 13:08:21 【问题描述】:

我在sparklyr 中有一些unix 时间转换为时间戳,出于某些原因,我还需要将它们转换为字符串。

不幸的是,在转换为字符串 hive 的过程中似乎转换为 EST(我的语言环境)。

df_new <- spark_read_parquet(sc, "/mypath/parquet_*",
                             overwrite = TRUE,
                             name = "df_new",
                             memory = FALSE,
                             options = list(mergeSchema = "true"))
> df_new %>%  
           mutate(unix_t = from_utc_timestamp(timestamp(t) ,'UTC'),
           date_str = date_format(unix_t, 'yyyy-MM-dd HH:mm:ss z'),
           date_alt = to_date(from_utc_timestamp(timestamp(t) ,'UTC'))) %>% 
    select(t, unix_t, date_str, date_alt) %>% head(5)
# Source:   lazy query [?? x 4]
# Database: spark_connection
            t unix_t              date_str                date_alt  
        <dbl> <dttm>              <chr>                   <date>    
1 1419547405. 2014-12-25 22:43:25 2014-12-25 17:43:25 EST 2014-12-25
2 1418469714. 2014-12-13 11:21:54 2014-12-13 06:21:54 EST 2014-12-13
3 1419126103. 2014-12-21 01:41:43 2014-12-20 20:41:43 EST 2014-12-20
4 1419389856. 2014-12-24 02:57:36 2014-12-23 21:57:36 EST 2014-12-23
5 1418271811. 2014-12-11 04:23:31 2014-12-10 23:23:31 EST 2014-12-10

您可以看到date_strdate_alt 都使用EST 时区。我在这里需要UTC。我该怎么做?

谢谢!

【问题讨论】:

查找 POSIXct。另外,我很确定月份和分钟的格式字符串是相反的。您可能需要仔细检查 我们在这里谈论火花,对吧? 这可能很有趣; ***.com/a/11237811 谢谢,但你确定这在 sparklyr 中有效吗?我不是在这里谈论base R 你真的在这里使用sparklyr而不是SparkR吗? 【参考方案1】:

从 Hive 函数参考中,date_format 使用 Java 的 SimpleDateFormat,我相信它始终默认为 JVM 时区,这解释了为什么这会将字符串转换为您的时区。

一种选择是检测时区并手动添加小时以获取 UTC。

另一种选择是将lubridatespark_apply() 一起使用:

sdf_len(sc, 1) %>%
  mutate(unix_t = from_utc_timestamp(timestamp(1522371003) , 'UDT')) %>%
  spark_apply(
    function(e) 
      dplyr::mutate(
        e,
        time_str = as.character(
          lubridate::with_tz(
            as.POSIXct(unix_t, origin="1970-01-01"),
            "GMT"
          )
        )
      )
    ,
    columns = c("id", "unix_t", "time_str"))

【讨论】:

太棒了!!!有用!有趣的是,在 spark_apply 之后,unix_t 列现在是 double(而之前是 dttm 令人费解的是to_date 似乎也使用时区语言环境...【参考方案2】:

sparklyr 可能会将一些奇怪的时区转换为 hive 函数。我会尝试将数据框注册为表格并使用纯 HQL 进行操作:

createOrReplaceTempView(df_new, "df_new")
result <- sql("select from_utc_timestamp(timestamp(t) ,'UTC'),
   cast(from_utc_timestamp(timestamp(t) ,'UTC') as STRING),
   cast(from_utc_timestamp(timestamp(t) ,'UTC') as DATE)
   from df_new")
head(result)

编辑

如果您不熟悉 SQL 语言,您可以像这样将 df_new 中的任何变量添加为逗号分隔列表(并使用 as 重命名您的选择)

select var1, var2, t,
   from_utc_timestamp(timestamp(t) ,'UTC') as unix_t,
   cast(from_utc_timestamp(timestamp(t) ,'UTC') as STRING) as date_str,
   cast(from_utc_timestamp(timestamp(t) ,'UTC') as DATE) as date_alt
   from df_new

您还可以使用 * 来表示数据框中的所有变量:

select *,
   from_utc_timestamp(timestamp(t) ,'UTC') as unix_t,
   cast(from_utc_timestamp(timestamp(t) ,'UTC') as STRING) as date_str,
   cast(from_utc_timestamp(timestamp(t) ,'UTC') as DATE) as date_alt
   from df_new

【讨论】:

你知道如何在上面的mutate中直接使用这些SQLcast吗? 我相信 mutate 中的所有转换都必须通过 R 函数完成,而这些是问题的根源,这就是为什么我建议使用 HQL 进行这种特殊操作的原因。是否有理由需要它在 mutate 中? 谢谢,我不需要变异,但我确实需要同一张表中的所有其他变量。 您可以将它们添加到选择中。如果您对 SQL 不熟悉,我将进行编辑以说明如何操作。【参考方案3】:

尝试使用 as.POSIXct() 吗?

format(as.POSIXct(unix_t, origin = unix_t, tz = "UTC", usetz=TRUE),"%Y-%m-%d %H:mm:ss") 

这将首先将 unix 时间戳转换为 UTC,然后格式化为所需的字符串。

【讨论】:

不起作用。这不是普通的 R,这是 Sparklyr!

以上是关于如何将时间戳转换为字符串(不更改时区)?的主要内容,如果未能解决你的问题,请参考以下文章

如何将字符串转换为带有时区的时间戳?

如何将“字符串”转换为“没有时区的时间戳”

Python:如何在不知道 DST 是不是生效的情况下将时区感知时间戳转换为 UTC

js 如何把一个本地时间 转换为其他时区的时间

Python pytz 将时间戳(字符串格式)从一个时区转换为另一个时区

在 VBA 中,如何以简单的方式将 UTC UNIX 时间戳转换为本地时区日期?