datatime使用场景
- CSV/JSON数据源使用模式字符串来解析和格式化日期时间内容。
- 日期时间函数用于转换StringType类型到DateType或TimestampType类型,反之亦然。例如,unix_timestamp, date_format, to_unix_timestamp, from_unixtime, to_date, to_timestamp, from_utc_timestamp, to_utc_timestamp等。
常用的模式字母
Spark使用下表中的模式字母进行日期和时间戳的解析和格式化:
模式字母的数量决定了日期时间的格式:
-
文本(Text):文本风格基于使用的模式字母数量确定。少于4个模式字母将使用简短文本形式,通常是缩写形式,例如,一周中的星期一可能会输出“Mon”。恰好4个模式字母将使用完整文本形式,通常是完整的描述,例如,一周中的星期一可能会输出“Monday”。5个或更多的字母将会导致失败。
-
数字(n):这里的n代表这种类型的日期时间模式可以使用的最大字母数量。
在格式化过程中,如果字母的数量为一个,则值将以最少的位数输出且不会填充;否则,字母的数量作为输出字段的宽度,必要时对值进行零填充。
在解析过程中,输入字段中期望的确切位数是必需的。 -
数字/文本:如果模式字母的数量为3个或更多,则使用上述的文本规则。否则,使用上述的数字规则。
-
小数部分(Fraction):使用一个或多个(最多9个)连续的’S’字符,例如SSSSSS,来解析和格式化秒的小数部分。对于解析,可接受的小数长度可以是[1, 连续的‘S’的数量]。对于格式化,小数长度会通过零填充扩展到连续的‘S’的数量。Spark支持微秒精度的日期时间,具有最多6位有效数字,但可以解析纳秒,超过的部分会被截断。
-
年份(Year):模式字母的数量决定了在何种字段宽度下使用填充。如果字母数量为两个,则使用缩短的两位数字形式。对于打印,这会输出最右边的两位数字。对于解析,这将使用基准值2000进行解析,结果年份将在2000到2099之间(含)。如果字母数量小于四个(但不是两个),则只有负年份才会输出符号。否则,当没有‘G’存在时,如果超过了填充宽度,则输出符号。7个或更多的字母将会导致失败。
-
月份(Month):它遵循数字/文本的规则。文本形式依赖于字母——‘M’表示‘标准’形式,而‘L’则是‘独立’形式。这两种形式只在某些语言中不同。例如,在俄语中,‘Июль’是七月的独立形式,而‘Июля’是标准形式。下面是所有支持的模式字母的例子:
-
‘M’ 或 ‘L’:一年中的月份编号,从1开始。‘M’和‘L’之间没有区别。1至9月在打印时不带填充。
spark-sql> select date_format(date '1970-01-01', "M"); 1 spark-sql> select date_format(date '1970-12-01', "L"); 12
-
‘MM’ 或 ‘LL’:一年中的月份编号,从1开始。对于1至9月,会添加零填充。
这意味着:
- 当使用 ‘MM’ 时,月份将以两位数字的形式显示,例如,1月将显示为 “01”,10月显示为 “10”。
- 同样地,当使用 ‘LL’ 时,如果遵循数字规则,也将以两位数字的形式显示月份,尽管 ‘L’ 通常用于表示月份的独立形式,但在这种上下文中,如果它是按照数字规则处理的,那么它也会显示为带有零填充的两位数字。
因此,无论是 ‘MM’ 还是 ‘LL’,只要它们遵循数字规则,1月至9月的月份都会被格式化为带有前导零的形式。
spark-sql> select date_format(date '1970-1-01', "LL"); 01 spark-sql> select date_format(date '1970-09-01', "MM"); 09
-
‘MMM’:标准形式下的简短文本表示。月份模式应该是日期模式的一部分,而不是单独的一个月份,除非在某些语言环境中标准形式和独立形式之间没有区别,比如在英语中。
这意味着:
- 当使用 ‘MMM’ 时,月份将以简短的文本形式输出,例如,1月可能会输出为 “Jan”,4月为 “Apr”。
- 此模式字母组合通常用于日期的上下文中,而不是单独用来表示月份。然而,在像英语这样的语言环境下,标准形式和独立形式相同,因此 ‘MMM’ 可以直接表示月份。
例如,在英语中,“January”(一月)的标准形式和独立形式都是 “Jan”,而在其他语言中,这两者可能会有所不同。在使用 ‘MMM’ 时,Spark 会根据所设置的语言环境来正确地输出或解析月份的简短文本形式。
spark-sql> select date_format(date '1970-01-01', "d MMM"); 1 Jan spark-sql> select to_csv(named_struct('date', date '1970-01-01'), map('dateFormat', 'dd MMM', 'locale', 'RU')); 01 янв.
-
‘LLL’:独立形式下的简短文本表示。它应该仅用于格式化/解析月份,而不包含任何其他的日期字段。
这意味着:
- 当使用 ‘LLL’ 时,月份将以简短的文本形式输出,例如,1月可能会输出为 “Jan”,4月为 “Apr”,但这是在独立形式下。
- 该模式字母组合专门用于单独表示月份,而不作为日期的一部分。即,它适用于那些需要单独表示月份而不涉及日期其他部分的场景。
例如,在英语中,如果需要单独表示一个月份而不涉及到具体的日期,那么可以使用 ‘LLL’ 来输出类似于 “Jan” 这样的简短文本形式。在其他语言环境下,标准形式和独立形式可能会有所不同,‘LLL’ 会根据所设置的语言环境输出正确的独立形式的月份简写。
spark-sql> select date_format(date '1970-01-01', "LLL"); Jan spark-sql> select to_csv(named_struct('date', date '1970-01-01'), map('dateFormat', 'LLL', 'locale', 'RU')); янв.
-
‘MMMM’:标准形式下的完整文本表示。它用于作为日期/时间戳的一部分来解析或格式化月份。
这意味着:
- 当使用 ‘MMMM’ 时,月份将以完整的文本形式输出,例如,1月可能会输出为 “January”,4月为 “April”。
- 该模式字母组合通常用于日期或时间戳的上下文中,而不是单独用来表示月份。它主要用于包含完整月份名称的日期格式。
例如,在英语中,“January”(一月)将以完整的文本形式出现。在使用 ‘MMMM’ 时,Spark 会根据所设置的语言环境来正确地输出或解析月份的完整文本形式。这对于需要完整月份名称的日期格式非常有用,尤其是在与其他日期组件(如日、年)一起使用时。
spark-sql> select date_format(date '1970-01-01', "d MMMM"); 1 January spark-sql> select to_csv(named_struct('date', date '1970-01-01'), map('dateFormat', 'd MMMM', 'locale', 'RU')); 1 января
-
‘LLLL’:独立形式下的完整文本表示。该模式可以仅用于格式化/解析月份。
这意味着:
- 当使用 ‘LLLL’ 时,月份将以完整的文本形式输出,例如,1月可能会输出为 “January”,4月为 “April”,但这是在独立形式下。
- 该模式字母组合专门用于单独表示月份,而不作为日期的一部分。即,它适用于那些需要单独表示月份而不涉及日期其他部分的场景。
例如,在英语中,如果需要单独表示一个月份而不涉及到具体的日期,那么可以使用 ‘LLLL’ 来输出类似于 “January” 这样的完整文本形式。在其他语言环境下,标准形式和独立形式可能会有所不同,‘LLLL’ 会根据所设置的语言环境输出正确的独立形式的月份全称。
spark-sql> select date_format(date '1970-01-01', "LLLL"); January spark-sql> select to_csv(named_struct('date', date '1970-01-01'), map('dateFormat', 'LLLL', 'locale', 'RU')); январь
-
-
am-pm:这会输出一天中的上午或下午。模式字母的数量必须是1。
这意味着:
- 使用单个字母 ‘a’ 作为模式字母时,将输出一天中的上午(AM)或下午(PM)。
- 例如,如果时间是上午10点,它将输出 “AM”;如果是下午2点,则会输出 “PM”。
- 模式字母的数量只能是一个,即 ‘a’,不能是多个,否则将不符合规范。
在Spark中,使用 ‘a’ 作为模式字母可以帮助在解析和格式化时间时正确地表示12小时制的时间系统中的上午或下午。
-
Zone ID (V):这会输出时区ID。模式字母的数量必须是2。
这意味着:
- 使用两个字母 ‘VV’ 作为模式字母时,将输出时区的标识符,例如 “PST”(太平洋标准时间)、“CET”(中部欧洲时间)等。
- 模式字母的数量必须是2,即 ‘VV’,不能是其他数量,否则将不符合规范。
在Spark中,使用 ‘VV’ 作为模式字母可以帮助在解析和格式化时间时正确地表示时间所在的时区。这在处理跨时区的数据时尤为重要,确保时间信息能够准确反映其对应的时区。
-
时区名称 (z):这会输出时区ID的文本名称。如果模式字母的数量为1、2或3个,则输出简短名称;如果模式字母的数量为4个,则输出完整名称。5个或更多的字母将导致失败。
这意味着:
- 使用1、2或3个 ‘z’ 作为模式字母时,将输出时区的简短名称,例如 “PDT”(太平洋夏令时)、“CET”(中部欧洲时间)等。
- 如果使用4个 ‘z’ 作为模式字母,则输出时区的完整名称,例如 “America/Los_Angeles”。
- 模式字母的数量不能是5个或更多,否则将不符合规范。
在Spark中,使用不同的 ‘z’ 字母数量可以帮助在解析和格式化时间时正确地表示时区的简短名称或完整名称。这对于需要精确表示数据所在时区的应用场景非常重要。
-
偏移量 (X 和 x):这会根据模式字母的数量来格式化偏移量。具体如下:
- 一个字母 ‘X’ 或 ‘x’ 输出仅小时部分,例如 ‘+01’。但如果分钟部分非零,则也会输出分钟部分,例如 ‘+0130’。
- 两个字母 ‘XX’ 或 ‘xx’ 输出小时和分钟,不带冒号,例如 ‘+0130’。
- 三个字母 ‘XXX’ 或 ‘xxx’ 输出小时和分钟,带冒号,例如 ‘+01:30’。
- 四个字母 ‘XXXX’ 或 ‘xxxx’ 输出小时、分钟以及可选的秒,不带冒号,例如 ‘+013015’。
- 五个字母 ‘XXXXX’ 或 ‘xxxxx’ 输出小时、分钟以及可选的秒,带冒号,例如 ‘+01:30:15’。
- 六个或更多的字母会导致失败。
另外,模式字母 ‘X’(大写)当输出的偏移量为零时会输出 ‘Z’,而模式字母 ‘x’(小写)当输出的偏移量为零时会分别输出 ‘+00’, ‘+0000’, 或 ‘+00:00’,具体取决于使用的字母数量。
这意味着:
- ‘X’ 和 ‘x’ 都可以根据不同的字母数量来表示不同的偏移格式。
- ‘X’ 特别之处在于当偏移量为零时会输出 ‘Z’,这在UTC时间(协调世界时)中常见。
- ‘x’ 在偏移量为零时会输出不同的形式,具体取决于使用的字母数量。
-
偏移量 (O):这会根据模式字母的数量来格式化本地化的偏移量。具体如下:
- 一个字母 ‘O’ 输出本地化偏移量的简短形式,这是一种本地化的偏移量文本,例如 ‘GMT’,小时部分不带前导零,如果分钟和秒非零则输出两位数的分钟和秒,并且带上冒号,例如 ‘GMT+8’。
- 四个字母 ‘OOOO’ 输出本地化偏移量的完整形式,这是一种本地化的偏移量文本,例如 ‘GMT’,带有两位数的小时和分钟字段,如果秒非零则输出秒字段,并且带上冒号,例如 ‘GMT+08:00’。
- 除了上述两种情况外,其他数量的字母都将导致失败。
这意味着:
- ‘O’ 可以用来表示本地化的时间偏移量,简短形式通常为 ‘GMT’ 加上正负号和小时数,如果分钟或秒非零则也包括这些部分。
- 完整形式则总是包括 ‘GMT’ 加上两位数的小时和分钟,并且如果秒非零的话也包括秒部分,各个部分之间用冒号分隔。
- 其他数量的字母将不会被支持,因此使用时需注意模式字母的数量。
-
偏移量 (Z):这会根据模式字母的数量来格式化偏移量。具体如下:
- 一个、两个或三个字母 ‘Z’ 输出小时和分钟,不带冒号,例如 ‘+0130’。当偏移量为零时,输出为 ‘+0000’。
- 四个字母 ‘ZZZZ’ 输出本地化偏移量的完整形式,相当于偏移量 ‘O’ 的四个字母形式。当偏移量为零时,输出为相应的本地化偏移量文本,例如 ‘GMT+0000’。
- 五个字母 ‘ZZZZZ’ 输出小时、分钟以及可选的秒(如果非零),并且带上冒号,例如 ‘+01:30:15’。当偏移量为零时,输出为 ‘Z’。
- 六个或更多的字母将导致失败。
这意味着:
- ‘Z’ 可以用来表示偏移量的不同形式,从简单的小时和分钟到详细的小时、分钟和秒。
- 当偏移量为零时,根据字母的数量,输出会有所不同:‘+0000’(1-3个字母)、本地化的零偏移文本(4个字母)、‘Z’(5个字母)。
- 超过五个字母的情况将不会被支持。
-
可选部分的开始和结束:使用方括号
[]
来定义一个可选部分,并且可以嵌套。在格式化过程中,即使是在可选部分中的所有有效数据也会被输出。在解析过程中,整个可选部分可以从解析的字符串中缺失。这意味着:
- 格式化:无论数据是否位于可选部分内,所有有效数据都会被输出。
- 解析:在解析时,如果某个可选部分的内容缺失,解析过程仍然可以继续,因为这部分是可选的。
例如:
-
如果你有一个日期时间格式
[yyyy-MM-dd] HH:mm:ss
,其中方括号内的部分是可选的。- 在格式化时,如果提供了年月日,将会输出完整的日期时间,例如
2024-08-26 10:18:00
。 - 在解析时,如果输入字符串缺少日期部分,如
10:18:00
,解析仍然可以成功,忽略方括号内的缺失部分。
- 在格式化时,如果提供了年月日,将会输出完整的日期时间,例如
-
方括号可以嵌套,例如
[[MM/dd/yyyy]] HH:mm:ss
,这样内外两层都可以是可选的。
使用方括号定义可选部分在处理不确定是否存在的数据部分时非常有用,特别是在解析不完全符合预期格式的数据时。
-
符号 ‘E’、‘F’、‘q’ 和 ‘Q’ 只能用于日期时间的格式化,例如在
date_format
函数中。它们不允许用于日期时间的解析,例如在to_timestamp
函数中。这意味着:
- 格式化:这些符号可以用来生成特定格式的日期时间字符串。例如,你可以使用这些符号来格式化日期时间,使其符合某种特定的显示需求。
- 解析:这些符号不能用于将字符串转换为日期时间对象。也就是说,在尝试从字符串中解析日期时间信息时,这些符号是无效的。
具体来说:
- ‘E’:表示一周中的某一天,通常用于格式化,如 “Mon” 或 “Monday”。
- ‘F’:表示一个月中的某一天,通常是一个数字,但不能用于解析。
- ‘q’:表示一年中的第几个季度,通常用于格式化。
- ‘Q’:表示一个季度中的某个月,通常用于格式化。
例如:
- 如果你使用
date_format
函数,你可以使用这些符号来格式化日期,如date_format("2024-08-26", "EEEE")
将返回 “Monday”。 - 但是,如果你试图使用
to_timestamp
函数来解析日期时间字符串,你不能使用这些符号,如to_timestamp("2024-08-26", "E")
将会抛出错误。
这些限制是为了确保在解析日期时间字符串时的一致性和准确性,防止因符号使用不当而导致的解析错误。
总结
SparkSQL中的日期时间模式,可能大部分人只了解其中的某部分内容,我们尽可能的把所有的日期模式进行一个全面的了解,这样在使用的时候就能游刃有余。
参考文献
https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html
标签:输出,01,字母,偏移量,日期,详解,SparkSQL,date,解析 From: https://blog.csdn.net/Android_xue/article/details/141552672