将日期转换为 ISO 星期日期

Posted

技术标签:

【中文标题】将日期转换为 ISO 星期日期【英文标题】:Convert date to ISO week date 【发布时间】:2020-04-03 13:21:35 【问题描述】:

如何在 Impala SQL 中将日期转换为 ISO week date?

例如,ISO 周日期日历中的2019-12-30 将写为2020-W01-12020W011

回答:

将 Gordon Linoff 的答案标记为正确,因为它解决了问题的基本部分,即推断 ISO 周日期的年份部分。

ISO星期日期的星期部分有一个准备好的功能,ISO星期日期的星期部分可以很容易地从星期日开始周转换为星期一开始周。

下面的查询包含从星期一到星期日的所有星期日期:

select datecol, 
       concat(cast(iso_year as string),'-W',lpad(cast(iso_week as string),2,'0'),'-',cast(iso_day as string)) as iso_Year_week_date_long,
       concat(cast(iso_year as string),'W',lpad(cast(iso_week as string),2,'0'),cast(iso_day as string)) as iso_Year_week_date_short
  from (
SELECT datecol, 
       (case when weekofyear(datecol) = 1 and
                  date_part('year',datecol) <> date_part('year',adddate(datecol,+7))
             then date_part('year',datecol) + 1
             when weekofyear(datecol) in (52, 53) and
                  date_part('year',datecol) <> date_part('year',adddate(datecol,-7))
             then date_part('year',datecol) - 1
             else date_part('year',datecol)
         end) as iso_year,
       weekofyear(datecol) as iso_week,
       1+mod(dayofweek(datecol)+5,7) as iso_day
  from (
  select '2021-12-31' as datecol union
  select '2020-12-31' as datecol union
  select '2019-12-31' as datecol union
  select '2018-12-31' as datecol union
  select '2017-12-31' as datecol union
  select '2016-12-31' as datecol union
  select '2015-12-31' as datecol union
  select '2014-12-31' as datecol union
  select '2013-12-31' as datecol union
  select '2012-12-31' as datecol union
  select '2022-01-01' as datecol union
  select '2021-01-01' as datecol union
  select '2020-01-01' as datecol union
  select '2019-01-01' as datecol union
  select '2018-01-01' as datecol union
  select '2017-01-01' as datecol union
  select '2016-01-01' as datecol union
  select '2015-01-01' as datecol union
  select '2014-01-01' as datecol union
  select '2013-01-01' as datecol
 ) as t1
  ) as t2
order by datecol;

并显示 1 月 1 日的归属

新年,如果 1 月 1 日是一周的第 1 天、第 2 天、第 3 天或第 4 天,即,如果在包含 1 月 1 日的一周中至少有 4 个新年日 旧年,如果 1 月 1 日是一周中的第 5 天、第 6 天或第 7 天,即,如果包含 1 月 1 日的一周中有 3 个或更少的新年日
datecol   |iso_year_week_date_long|iso_year_week_date_short|
----------|-----------------------|------------------------|
2014-12-31|2015-W01-3             |2015W013                |
2015-01-01|2015-W01-4             |2015W014                |
2015-12-31|2015-W53-4             |2015W534                |
2016-01-01|2015-W53-5             |2015W535                |
2016-12-31|2016-W52-6             |2016W526                |
2017-01-01|2016-W52-7             |2016W527                |
2017-12-31|2017-W52-7             |2017W527                |
2018-01-01|2018-W01-1             |2018W011                |
2018-12-31|2019-W01-1             |2019W011                |
2019-01-01|2019-W01-2             |2019W012                |
2019-12-31|2020-W01-2             |2020W012                |
2020-01-01|2020-W01-3             |2020W013                |
2020-12-31|2020-W53-4             |2020W534                |
2021-01-01|2020-W53-5             |2020W535                |

【问题讨论】:

您的意思是仅当impala.apache.org/docs/build/html/topics/… 返回53 时?或者一年中的任何一天? @caius-jard 该问题试图找到从日期值到相应 ISO 周日期的通用转换.. 【参考方案1】:

认为 Impala 返回 date_part()extract() 的 iso 周 -- 基于您之前的问题。没有这方面的文档。

如果是这样,您可以使用条件逻辑:

select (case when date_part(week, datecol) = 1 and
                  date_part(year, datecol) <> date_part(year, datecol + interval 1 week)
             then date_part(year, datecol) + 1
             when date_part(week, datecol) in (52, 53) and
                  date_part(year, datecol) <> date_part(year, datecol - interval 1 week)
             then date_part(year, datecol) - 1
             else date_part(year, datecol)
         end) as iso_year,
        date_part(week, datecol) as iso_week

否则,您可以使用以下方法获取 iso 年的第一天:

select (case when to_char('DD', date_trunc(year, datecol), 'DD') in ('THU', 'FRI', 'SAT', 'SUN')
             then next_day(date_trunc(year, date_trunc(year, datecol)), 'Monday')
             else next_day(date_trunc(year, date_trunc(year, datecol)), 'Monday') - interval 7 day
         end) as iso_year_start 

然后,您可以使用算术计算从 iso 年开始的 iso 周。

【讨论】:

这个算法似乎确实有效。将创建问题的答案并将其标记为正确。 将此标记为正确答案并创建了与该问题相关的完整示例。 只是一个小问题;第二个提案在国际上是安全的吗,或者如果在安装在法国语言环境中的服务器上运行它会返回一组不同的名称? @CaiusJard 。 . .第二个答案取决于工作日的名称,因此它仅适用于英语。该文档没有EXTRACT() 的“工作日”选项,但如果它被实施我不会感到惊讶。【参考方案2】:

例如,ISO 周日期日历中的 2019-12-30 将写为 2020-W01-1 或 2020W011。

我们可以使用字符串格式:

select cast(cast('2019-12-30' as date format 'YYYY-MM-DD') as string format 'iyyy-iw-id')

返回:

"2020-01-01"

【讨论】:

以上是关于将日期转换为 ISO 星期日期的主要内容,如果未能解决你的问题,请参考以下文章

如何将UTC秒数转换为日期,100分,在线等

在javascript中将iso日期转换为毫秒

Swift:将 ISO8601 转换为日期

如何将 Excel 中的日期转换为 ISO 8601 格式

Oracle 将 ISO 日期转换为计算机区域设置日期/时间

ISO日期格式从字符串到日期的转换会出错?