【问题标题】:Datetime: Calcul Hours in days日期时间:以天为单位计算小时数
【发布时间】:2018-04-24 22:53:19
【问题描述】:

我有 3 个 scala 函数,运行良好,只是函数中有错误

我做了另一个函数 equals:通过调用上面的 3 个函数来计算两个日期之间的小时数:toEnd、ToStart、jourOuvree。 我在一个 scala 对象中编写了所有函数。但是当我运行equals函数时,它给了我一个错误,如下:

                                     ^

我应该使用该函数并将其应用于我的数据框以计算两个日期之间的小时数。

我在 java.time API 方面并不出色。 有人可以帮我解决这些错误吗?

【问题讨论】:

  • 能否提供jourOuvreetoEndtoStart的签名?
  • 你的意思是签名那里有代码?如果需要,我可以编辑我的问题?
  • 是的,我的意思是函数代码
  • 我从一开始就编辑了我的问题,我希望这很清楚。对不起,因为代码有点长。我正在研究如何解析函数等于调用其他三个函数(toEnd、ToStart 和 jourouvree),因为之后我应该将它应用到我的数据帧上。非常感谢
  • 你的代码做了很多没有意义的事情。这是一个:这个签名jourOuvree(String,String):Unit 意味着该方法不返回任何东西(Unit)。因此这个toEnd(LocalTime.of(d1))+jourOuvree(... 是不可能的。您不能将 Unit 添加到值中。

标签: scala datetime


【解决方案1】:

我重写了您的解决方案。见内联 cmets。

import java.time._
import java.time.temporal.ChronoUnit

import scala.annotation.tailrec
import scala.concurrent.duration._

object Demo extends App {

  val start = LocalTime.of(9, 0)
  val midEnd = LocalTime.of(13, 0)
  val midStart = LocalTime.of(14, 0)
  val end = LocalTime.of(18, 0)
  val firstHalf = start.until(midEnd, ChronoUnit.MILLIS).millis
  val secondHalf = midStart.until(end, ChronoUnit.MILLIS).millis

  implicit class formatter(d: FiniteDuration) {
    def withMinutes = {
      val l = d.toMinutes
      s"${l / 60}:${l % 60}"
    }

    def withSeconds = s"${d.toHours}:${d.toMinutes % 60}:${d.toSeconds % 60}"
  }

  // check if day is working. Could be easily adjusted to check not only weekend but holidays as well
  def isWorkingDay(d: LocalDate) = !Set(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY).contains(d.getDayOfWeek)
  // check if current day is working day and if not switch to next start of day/previous end of day
  // depending on ask parameter
  @tailrec
  def adjust(t: LocalDateTime, asc: Boolean = true): LocalDateTime = {
    if (!isWorkingDay(t.toLocalDate) && asc) adjust(t.toLocalDate.plusDays(1).atTime(start), asc)
    else if (!isWorkingDay(t.toLocalDate) && !asc) adjust(t.toLocalDate.minusDays(1).atTime(end), asc)
    else t
  }

  def toEnd(t: LocalTime) = {
    if (t.isBefore(start)) firstHalf + secondHalf
    else if (t.isBefore(midEnd)) t.until(midEnd, ChronoUnit.MILLIS).millis + secondHalf
    else if (t.isBefore(midStart)) secondHalf
    else if (t.isBefore(end)) t.until(end, ChronoUnit.MILLIS).millis
    else 0.hours
  }


  def toStart(t: LocalTime) = {
    if (t.isBefore(start)) 0.hours
    else if (t.isBefore(midEnd)) start.until(t, ChronoUnit.MILLIS).millis
    else if (t.isBefore(midStart)) firstHalf
    else if (t.isBefore(end)) firstHalf + midStart.until(t, ChronoUnit.MILLIS).millis
    else firstHalf + secondHalf
  }

  // count amount of working days between two dates.
  // if dates are the same - means 0 days
  def jourOuvree(d1: LocalDate, d2: LocalDate): Int = {
    @tailrec
    def count(n: LocalDate, acc: Int): Int = {
      if (n.isEqual(d2) || n.isAfter(d2)) acc
      else if (!isWorkingDay(n)) count(n.plusDays(1), acc)
      else count(n.plusDays(1), acc + 1)
    }

    count(d1, 0)
  }

  // evaluate duration of working time between to date/times
  // take into account that start/end could be non-working and
  // adjust
  def toEquals(rd1: LocalDateTime, rd2: LocalDateTime) = {
    val d1 = adjust(rd1)
    val d2 = adjust(rd2, asc = false)
    // if we are in the same day ==> I should compute just a difference between hours
    if (d1.isAfter(d2)) 0.hours
    else if (d1.toLocalDate.isEqual(d2.toLocalDate)) {
      toEnd(d1.toLocalTime) - toEnd(d2.toLocalTime)
    }
    else {
      toEnd(d1.toLocalTime) + jourOuvree(d1.toLocalDate.plusDays(1), d2.toLocalDate.minusDays(1)) * 8.hours + toStart(d2.toLocalTime)
    }
  }

  val thursdayStart = LocalDate.of(2018, 3, 1).atTime(start)
  val thursdayEnd = LocalDate.of(2018, 3, 1).atTime(end)
  val fridayStart = LocalDate.of(2018, 3, 2).atTime(start)
  val fridayEnd = LocalDate.of(2018, 3, 2).atTime(end)
  val saturdayStart = LocalDate.of(2018, 3, 3).atTime(start)
  val saturdayEnd = LocalDate.of(2018, 3, 3).atTime(end)
  val sundayStart = LocalDate.of(2018, 3, 4).atTime(start)
  val sundayEnd = LocalDate.of(2018, 3, 4).atTime(end)
  val mondayStart = LocalDate.of(2018, 3, 5).atTime(start)
  val mondayEnd = LocalDate.of(2018, 3, 6).atTime(end)
  println(toEquals(thursdayStart, sundayStart).withSeconds)
  println(toEquals(thursdayStart, saturdayStart).withSeconds)
  println(toEquals(thursdayStart, mondayStart).withSeconds)
  println(toEquals(thursdayStart, mondayEnd).withSeconds)
  println(toEquals(thursdayStart, thursdayEnd).withSeconds)

  // formatter to use to parse string input
  import java.time.format.DateTimeFormatter
  val DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
  println(toEquals(LocalDateTime.parse("2018-03-01 11:22:33", DATE_TIME_FORMATTER), LocalDateTime.parse("2018-03-02 11:22:33", DATE_TIME_FORMATTER)).withSeconds)
}

【讨论】:

  • 感谢您的回答。我有这个错误,当它找到 LocalDate 或 LocalTime 或 LocalDateTime 时,它​​显示此错误:错误:对 LocalDate 的引用不明确;它通过 import java.time._ 和 import org.joda.time._ 在同一范围内导入两次。我为每一个添加了一个导入:import org.joda.time.{LocalTime => MessagesLocalTime} import java.time。 {LocalTime => MessagesLocalTime} 但它不能解决错误
  • 我没有在我的解决方案中使用 joda.time。您还应该使用 java.time 或 joda.time,但不能混合使用。它们提供等效的功能,在 joda 站点上建议使用 java.time。
  • 打扰一下,是的,你有权我应该使用 joda 或 java。然后,我运行Object Demo,它编译得很好,谢谢,但是我尝试运行toEquals函数来验证,通过在示例中引入2个日期:toEquals("2018-03-23 12:44:24"," 2018-03-28 15:45:46") 它显示:toEquals("2018-03-23 12:44:24","2018-03-28 15:45:46") :137: 错误: 未找到: value toEquals toEquals("2018-03-23 12:44:24","2018-03-28 15:45:46") 如何运行它,以验证因为我应该在 2 之后应用一个函数我的数据框中的字段 LocalDateTime(start_date, finish_date)。
  • 添加了格式化程序和字符串日期输入示例
  • 非常抱歉,我无法理解如何运行该功能。我做了 toEquals(LocalDateTime.parse("2018-03-01 11:22:33", DATE_TIME_FORMATTER), LocalDateTime.parse("2018-03-02 11:22:33", DATE_TIME_FORMATTER)).withSeconds,我也做了toEquals("2018-03-23 12:24:44","2018-04-03 10:22:44") 但它总是显示错误。请你给我一个例子,我如何通过引入 2 个日期来运行它。谢谢
猜你喜欢
  • 2023-03-11
  • 2022-06-29
  • 2018-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-03
相关资源
最近更新 更多