2 回答
TA贡献1828条经验 获得超4个赞
首先,让我们澄清您的输入数据。您提到过,您有Timestamp,但您列出的输出格式似乎只是字符串值,表示以下格式yyyy-MM-dd'T'HH:mm:ss.SSSZ。你能证实这个结论吗?
在您的一条评论中,您回答该函数在您的尝试中unix_timestamp返回。null查看unix_timestamp(Column s, String p)的文档,我们可以看到它需要其他格式来解析,否则它会返回null:
参数:
s - 日期、时间戳或字符串。如果是字符串,则数据必须采用可以转换为时间戳的格式,例如yyyy-MM-dd或yyyy-MM-dd HH:mm:ss.SSSS
fmt - 详细说明 s 格式的日期时间模式当 s 是字符串时
返回:
时间戳,如果 s 是无法转换为时间戳的字符串或 fmt 是无效格式,则返回null
如果您输入的参数确实是字符串,我建议您使用以下解决方案,使用 Spark SQL 函数to_timestamp(Column s, String fmt)和date_format(Column dateExpr, String format)
import static org.apache.spark.sql.functions.col;
import static org.apache.spark.sql.functions.to_timestamp;
import static org.apache.spark.sql.functions.date_format;
....
SparkSession spark = SparkSession
.builder()
.appName("datetime-transformation")
.master("local[*]")
.getOrCreate();
SomeDto someDto = SomeDto.builder()
.id("abc1")
.lastModif("2019-01-14T19:51:55.123+02:00")
.created("2019-01-14T19:51:55.123+02:00")
.build();
Dataset<Row> ds = spark.createDataset(Collections.singletonList(someDto), Encoders.bean(SomeDto.class)).toDF();
ds.printSchema();
ds.show(false);
Dataset<Row> dfm = ds
.withColumn("lastModif", to_timestamp(col("lastModif"), "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"))
.withColumn("created", date_format(to_timestamp(col("lastModif"), "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"), "yyyy-MM-dd"));
dfm.printSchema();
dfm.show(false);
输出将是:
root
|-- created: string (nullable = true)
|-- id: string (nullable = true)
|-- lastModif: string (nullable = true)
+-----------------------------+----+-----------------------------+
|created |id |lastModif |
+-----------------------------+----+-----------------------------+
|2019-01-14T19:51:55.123+02:00|abc1|2019-01-14T19:51:55.123+02:00|
+-----------------------------+----+-----------------------------+
root
|-- created: string (nullable = true)
|-- id: string (nullable = true)
|-- lastModif: timestamp (nullable = true)
+----------+----+-----------------------+
|created |id |lastModif |
+----------+----+-----------------------+
|2019-01-14|abc1|2019-01-14 19:51:55.123|
+----------+----+-----------------------+
TA贡献2037条经验 获得超6个赞
这就是我使映射动态化的方式:
private static Dataset<Row> mapColumns(Properties mappings, String tableNm, String[] colArr, Dataset<Row> tempDS) throws Exception
{
String mappedCols = "lastmodif,createdDate,endDate";
Dataset<Row> filtered = null;
Properties mappingCols = mappings;
List<String> mapped = Arrays.asList(mappedCols.split(","));
List<String> colsList = Arrays.asList(colArr);
ArrayList<String> tempList = new ArrayList<String>();
Iterator itrTmp = colsList.iterator();
while(itrTmp.hasNext()){
tempList.add((String)itrTmp.next());
}
Iterator itr = mapped.iterator();
filtered = tempDS.selectExpr(convertListToSeq(colsList));
while(itr.hasNext()){
String column = itr.next().toString();
String newCol = column+"_mapped";
String propertyKey = tableNm+"-"+column;
String propertyValue = mappingCols.getProperty(propertyKey);
filtered = filtered.selectExpr(convertListToSeq(colsList))
.withColumn(newCol, functions.regexp_replace(functions.substring(filtered.col(column), 0, 23),"T", " ")).alias(newCol)
.drop(filtered.col(column));
tempList.remove(column);
tempList.add(newCol);
colsList = tempList;
}
filtered = filtered.selectExpr(convertListToSeq(colsList));
filtered.show(false);
}
public static Seq<String> convertListToSeq(List<String> inputList)
{
return JavaConverters.asScalaIteratorConverter(inputList.iterator()).asScala().toSeq();
}
但是StringtoTimestamp转换仍然悬而未决。截至目前,我正在做一个substring, 但是这个逻辑适用于所有数据类型为yyyy-mm-ddThh:mm:ss.SSSZ等yyyy-mm-ddThh:mm:ss.SSS+0000的列,但如果列具有类型yyyy-mm-dd的数据并且代码将中断,则该逻辑将不起作用。我在这里提出了这个:如何将字符串转换为时间戳。
添加回答
举报
