pie*_*rop 6 python java date-formatting apache-spark pyspark
我pyspark 在macOS Sierra上遇到了一个非常奇怪的问题.我的目标是以ddMMMyyyy格式解析日期(例如:),31Dec1989但会收到错误.我运行Spark 2.0.1,Python 2.7.10和Java 1.8.0_101.我也试过使用Anaconda 4.2.0(它附带Python 2.7.12),但也得到了错误.
Ubuntu Server 15.04上具有相同Java版本和Python 2.7.9的相同代码可以正常运行而不会出现任何错误.
关于州的官方文件spark.read.load():
dateFormat- 设置指示日期格式的字符串.自定义日期格式遵循以下格式java.text.SimpleDateFormat.这适用于日期类型.如果设置为None,则使用默认值valueyyyy-MM-dd.
该官方Java文档有关谈判MMM的正确的格式解析如月的名字Jan,Dec等等,但它抛出了很多开始的错误java.lang.IllegalArgumentException.文档说明LLL也可以使用,但pyspark不识别它并抛出pyspark.sql.utils.IllegalArgumentException: u'Illegal pattern component: LLL'.
我知道另一个解决方案dateFormat,但这是解析数据的最快方法和最简单的代码.我在这里错过了什么?
为了运行下面的例子你只需要放置test.csv并test.py在同一目录下,然后运行<spark-bin-directory>/spark-submit <working-directory>/test.py.
ddMMMyyyy格式我有一个名为test.csv包含以下两行的纯文本文件:
col1
31Dec1989
Run Code Online (Sandbox Code Playgroud)
代码如下:
from pyspark.sql import SparkSession
from pyspark.sql.types import *
spark = SparkSession \
.builder \
.appName("My app") \
.config("spark.some.config.option", "some-value") \
.getOrCreate()
struct = StructType([StructField("column", DateType())])
df = spark.read.load( "test.csv", \
schema=struct, \
format="csv", \
sep=",", \
header="true", \
dateFormat="ddMMMyyyy", \
mode="FAILFAST")
df.show()
Run Code Online (Sandbox Code Playgroud)
我收到错误.我还尝试在日期和年份之前或之后移动月份名称(例如:1989Dec31和yyyyMMMdd),但没有成功.
ddMMyyyy格式的工作示例此示例与前一个示例相同,但日期格式除外.test.csv现在包含:
col1
31121989
Run Code Online (Sandbox Code Playgroud)
以下代码打印以下内容test.csv:
from pyspark.sql import SparkSession
from pyspark.sql.types import *
spark = SparkSession \
.builder \
.appName("My app") \
.config("spark.some.config.option", "some-value") \
.getOrCreate()
struct = StructType([StructField("column", DateType())])
df = spark.read.load( "test.csv", \
schema=struct, \
format="csv", \
sep=",", \
header="true", \
dateFormat="ddMMyyyy", \
mode="FAILFAST")
df.show()
Run Code Online (Sandbox Code Playgroud)
输出如下(我省略了各种冗长的行):
+----------+
| column|
+----------+
|1989-12-31|
+----------+
Run Code Online (Sandbox Code Playgroud)
UPDATE1
我创建了一个简单的Java类,它使用java.text.SimpleDateFormat:
import java.text.*;
import java.util.Date;
class testSimpleDateFormat
{
public static void main(String[] args)
{
SimpleDateFormat format = new SimpleDateFormat("yyyyMMMdd");
String dateString = "1989Dec31";
try {
Date parsed = format.parse(dateString);
System.out.println(parsed.toString());
}
catch(ParseException pe) {
System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
}
}
}
Run Code Online (Sandbox Code Playgroud)
此代码不适用于我的环境并抛出此错误:
java.text.ParseException: Unparseable date: "1989Dec31"
Run Code Online (Sandbox Code Playgroud)
但在另一个系统(Ubuntu 15.04)上完美运行.这似乎是一个Java问题,但我不知道如何解决它.我安装了最新的Java版本,并且我的所有软件都已更新.
有任何想法吗?
UPDATE2
我已经找到了如何通过指定Locale.US以下内容使其在纯Java下工作:
import java.text.*;
import java.util.Date;
import java.util.*;
class HelloWorldApp
{
public static void main(String[] args)
{
SimpleDateFormat format = new SimpleDateFormat("yyyyMMMdd", Locale.US);
String dateString = "1989Dec31";
try {
Date parsed = format.parse(dateString);
System.out.println(parsed.toString());
}
catch(ParseException pe) {
System.out.println(pe);
System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,问题变成:如何指定Java的Locale pyspark?
可能值得注意的是,这个问题已于 2016 年 10 月 24 日在Spark 邮件列表中得到解决。根据原始发布者:
这无需设置其他选项即可工作:
spark/bin/spark-submit --conf "spark.driver.extraJavaOptions=-Duser.language=en" test.py
并在 Spark 2.0.1 中被报告为SPARK-18076(将 DateFormat、NumberFormat 中使用的默认区域设置修复为 Locale.US),并在 Spark 2.1.0 中得到解决。
--conf "spark.driver.extraJavaOptions=-Duser.language=en"此外,虽然如果使用 Spark 2.1.0,则不再需要针对提交者提出的特定问题使用上述解决方法(传入),但一个显着的副作用是,对于 Spark 2.1.0 用户,您不能再传入类似的内容--conf "spark.driver.extraJavaOptions=-Duser.language=fr"如果您想解析非英语日期,例如“31mai1989”。
事实上,从 Spark 2.1.0 开始,当使用spark.read()加载 csv 时,我认为不再可能使用该dateFormat选项来解析诸如“31mai1989”之类的日期,即使您的默认区域设置是法语。我甚至将操作系统中的默认区域和语言更改为法语,并传递了我能想到的几乎所有区域设置排列,即
JAVA_OPTS="-Duser.language=fr -Duser.country=FR -Duser.region=FR" \
JAVA_ARGS="-Duser.language=fr -Duser.country=FR -Duser.region=FR" \
LC_ALL=fr_FR.UTF-8 \
spark-submit \
--conf "spark.driver.extraJavaOptions=-Duser.country=FR -Duser.language=fr -Duser.region=FR" \
--conf "spark.executor.extraJavaOptions=-Duser.country=FR -Duser.language=fr -Duser.region=FR" \
test.py
Run Code Online (Sandbox Code Playgroud)
却无济于事,导致
java.lang.IllegalArgumentException
at java.sql.Date.valueOf(Date.java:143)
at org.apache.spark.sql.catalyst.util.DateTimeUtils$.stringToTime(DateTimeUtils.scala:137)
Run Code Online (Sandbox Code Playgroud)
但同样,这仅影响 Spark 2.1.0 中解析非英语日期。