如何为模式yyyy/mm/dd/hh生成带有datetimeformat的路径

pftdvrlh  于 2021-05-27  发布在  Spark
关注(0)|答案(2)|浏览(422)

我使用spark/scala从s3加载文件。我的文件位于:

s3://bucket/yyyy/mm/dd/HH/parts...files

我需要用startdate(string)和enddate(string)生成文件路径

import org.joda.time.{DateTime, DateTimeZone}
import org.joda.time.Days
import org.joda.time.DurationFieldType
import org.joda.time.LocalDate
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter

val startDate = "2016-09-25T04:00:00Z"

val endDate = "2016-10-23T04:00:00Z"

val s3Bucket = "s3://test_bucket/"

def getUtilDate(timestamp: String): java.sql.Date =  new java.sql.Date(new DateTime(timestamp, DateTimeZone.UTC).toDate().getTime())

val start = new LocalDate(getUtilDate(startDate))

val end = new LocalDate(getUtilDate(endDate))

val days: Int = Days.daysBetween(start, end).getDays

    val files: Seq[String] = (0 to days)
      .map(start.plusDays)
      .map(d => s"$s3Bucket${DateTimeFormat.forPattern("yyyy/MM/dd/HH").print(d)}/*")

val testFiles =  sc.textFile(files.mkString(","), 20000)

val df = sqlContext.read.json(testFiles)

因为sqlcontext.read.json()不采用多个路径。
但这并没有给hh。它显示为 s3://test_bucket/2016/09/26/��/* 有人能告诉我为什么hh显示为��. 有没有办法让我在两天之间,也就是两天之间 "2016-09-25T04:00:00Z" and "2016-10-23T04:00:00Z" 就像

s3://test_bucket/2016/09/25/04/*.....
           to......s3://test_bucket/2016/10/23/04/*
ttp71kqs

ttp71kqs1#

你用过 LocalDate 它是一个只包含日期的类,它显式地不包含时间信息(这与 java.sql.Date 包含时间和日期信息)。因此,joda无法将“hh”呈现为hour,因为它没有该信息。
请尝试:

val startDate = "2016-09-25T04:00:00Z"

val endDate = "2016-10-23T04:00:00Z"

val s3Bucket = "s3://test_bucket/"

def getUtilDate(timestamp: String): org.joda.time.DateTime =
  new DateTime(timestamp, DateTimeZone.UTC)

val start = getUtilDate(startDate)

val end = getUtilDate(endDate)

val days: Int = Days.daysBetween(start, end).getDays

val files: Seq[String] = (0 to days)
  .map(start.plusDays)
  .map(d => s"$s3Bucket${DateTimeFormat.forPattern("yyyy/MM/dd/HH").print(d)}/*")

println(files)

更新:列出两天之间的所有小时数

要列出两个日期时间之间的每小时,需要从 startend ,每次使用“plushours”。在大多数语言中,都会使用“for”循环,但scala没有c风格的for循环。在scala中有两种主要的方法来实现这一点;我已经展示了以下两个方面:

val startDate = "2016-09-25T04:00:00Z"
val endDate = "2016-10-23T04:00:00Z"

val s3Bucket = "s3://test_bucket/"

def getUtilDate(timestamp: String): org.joda.time.DateTime =
  new DateTime(timestamp, DateTimeZone.UTC)

val start = getUtilDate(startDate)
val end = getUtilDate(endDate)

val fmt = DateTimeFormat.forPattern("yyyy/MM/dd/HH")
def bucketName(date: DateTime): String = s"$s3Bucket${fmt.print(date)}"

{
  // Imperative style:
  var t = start
  val files = mutable.Buffer[String]()
  do {
    files += bucketName(t)
    t = t.plusHours(1)
  } while (t.compareTo(end) < 0)

  println(files)
}

{
  // Functional style:
  @tailrec
  def loop(t: DateTime, acc: Seq[String]): Seq[String] = t match {
    case `end` => acc
    case _ =>
      loop(
        t.plusHours(1),
        acc :+ bucketName(t))
  }

  val files = loop(start, Vector())

  println(files)
}
wfauudbj

wfauudbj2#

你可以用 ChronoUnit 两次约会的时差。

val minutes = ChronoUnit.HOURS.between(dateTime, LocalDateTime.now())

相关问题