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

How to generate Path with DateTimeFormat for pattern yyyy/mm/dd/HH

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

您可以使用 ChronoUnit 来获取两个日期之间的小时差。

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

您使用了 LocalDate,这是一个纯日期 class,它明确不包含时间信息(这与包含时间和日期信息的 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)

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

要列出两个日期时间之间的每个小时,您需要从 start 循环到 end,每次使用 "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)
}