如何使用DateTimeFormat为模式yyyy / mm / dd / HH生成Path

时间:2016-10-23 23:35:33

标签: scala date apache-spark amazon-s3 jodatime

我正在使用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/*

2 个答案:

答案 0 :(得分:2)

您使用了LocalDate这是一个仅限日期的类,它明确地不包含时间信息(这与包含时间和日期信息的java.sql.Date不同)。因此,Joda无法将“HH”渲染为小时,因为它没有该信息。

尝试改为:

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)

更新:列出日期之间的所有小时数

要列出两个DateTime之间的每小时,您需要从start循环到end,每次都使用“plusHours”。在大多数语言中,你会使用“for”循环,但Scala没有C风格的循环。在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)
}

答案 1 :(得分:1)

您可以使用ChronoUnit获取两个日期之间的HOURS差异。

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