在 Swift 中将小数时间转换为小时和分钟

Rob*_*son 3 function swift calculation

我是编程新手,这是我的第一个程序和问题。我正在尝试编写一个函数,它将简单地将小数时间转换为小时和分钟。我删除小时并将小数分钟乘以 60,然后将两者作为字符串加在一起。我需要在我的程序中使用这个设施几次,因此这个功能。使用这个函数的计算很简单,但我得到了奇怪的结果。如果我将“plannedStartFuel”保持为 450 并调整“minLandAllowance”,我会得到以下结果,

185 returns 1:28
182 returns 1:29
181 returns 1:30
180 returns 2:30
179 returns 2:30
175 returns 2:32
Run Code Online (Sandbox Code Playgroud)

正确答案是 1:00 数字。我不明白为什么程序似乎在180点的结果上增加了一个小时。我确信有比我使用过的更好的方法来完成此计算,但如果您能提供帮助,我将不胜感激地知道哪个部分导致了错误以及原因。我尝试过什么?...一切!如果你向一个 7 岁的孩子提出你的答案,我可能有机会理解。谢谢。

import UIKit
import Foundation

func decimalHoursConv (hours : Double) -> (_hrs:String, mins:String) {

    let remainder = hours.truncatingRemainder(dividingBy: 1) * 60
    let mins = (String(format: "%.0f", remainder))

    let hrs = (String(format: "%.0f", hours))

    return (hrs, mins)
}
var plannedStartFuel = Double (0)
var minLandAllowance = Double (0)
var flyingTimeToMLA = Double(0)

plannedStartFuel = 450
minLandAllowance = 180

flyingTimeToMLA = ((plannedStartFuel - minLandAllowance) / 3)/60

let MLAtime = (decimalHoursConv(hours: flyingTimeToMLA))

print ("Flight Time To MLA =", MLAtime.0,"hrs",MLAtime.1,"mins")
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 5

我可能建议根本不要费心计算小时和分钟,而是让我们DateComponentsFormatter这样做,为您创建最终的字符串。

\n

例如:

\n
let formatter: DateComponentsFormatter = {\n    let formatter = DateComponentsFormatter()\n    formatter.unitsStyle = .full\n    formatter.allowedUnits = [.hour, .minute]\n    return formatter\n}()\n
Run Code Online (Sandbox Code Playgroud)\n

然后向此格式化程序提供以秒为单位测量的经过时间( a TimeInterval,它只是 的别名Double):

\n
let remaining: TimeInterval = 90 * 60 // e.g. 90 minutes represented in seconds\n\nif let result = formatter.string(from: remaining) {\n    print(result)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在英语设备上,这将产生:

\n
\n

1小时30分钟

\n
\n

这种方法的优点在于,它不仅使您无需亲自手动计算小时和分钟,而且还可以轻松本地化结果。因此,如果您开始本地化您的应用程序,该字符串也会自动为您本地化,而无需您做进一步的工作。例如,如果您将德语添加到应用程序本地化中,那么美国用户仍然会看到上述内容,但在德国设备上,它将生成:

\n
\n

1 秒和 30 分钟

\n
\n
\n

如果您想让它显示剩余时间,请设置includesTimeRemainingPhrase

\n
let formatter: DateComponentsFormatter = {\n    let formatter = DateComponentsFormatter()\n    formatter.unitsStyle = .full\n    formatter.includesTimeRemainingPhrase = true\n    formatter.allowedUnits = [.hour, .minute]\n    return formatter\n}()\n
Run Code Online (Sandbox Code Playgroud)\n

这将产生:

\n
\n

还剩 1 小时 30 分钟

\n
\n

如果你想要 \xe2\x80\x9chh:mm\xe2\x80\x9d 的表示形式:

\n
let formatter: DateComponentsFormatter = {\n    let formatter = DateComponentsFormatter()\n    formatter.unitsStyle = .positional\n    formatter.zeroFormattingBehavior = .pad\n    formatter.allowedUnits = [.hour, .minute]\n    return formatter\n}()\n
Run Code Online (Sandbox Code Playgroud)\n

将产生:

\n
\n

01:30

\n
\n
\n

顺便说一句,如果您想知道如何获得商和余数(特别是避免示例中不需要的舍入),请参阅文档truncatingRemainder(dividingBy:) 其中说:

\n
\n

使用截断除法返回该值除以给定值的余数。

\n

使用浮点值执行截断除法会产生截断的整数商和余数。对于值xy和\n它们的截断整数商q,余数r满足\n x == y * q + r

\n

以下示例计算\n8.625 除以 0.75 的截断余数:

\n
let x = 8.625\nprint(x / 0.75)\n// Prints "11.5"\n\nlet q = (x / 0.75).rounded(.towardZero)\n// q == 11.0\nlet r = x.truncatingRemainder(dividingBy: 0.75)\n// r == 0.375\n\nlet x1 = 0.75 * q + r\n// x1 == 8.625\n
Run Code Online (Sandbox Code Playgroud)\n

如果该值 和other都是有限数,则截断余数与该值具有相同的符号,并且在大小上严格小于other。该truncatingRemainder(dividingBy:)方法总是准确的。

\n
\n

我可能倾向于写一个浮点再现quotientAndRemainder

\n
extension FloatingPoint {\n    func quotientAndRemainder(dividingBy divisor: Self) -> (Self, Self) {\n        let q = (self / divisor).rounded(.towardZero)\n        let r = truncatingRemainder(dividingBy: divisor)\n        return (q, r)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后,在您的示例中,使用该方法:

\n
func decimalHoursConv(hours input: Double) -> (_hrs: String, mins: String) {\n    let (q, r) = input.quotientAndRemainder(dividingBy: 1)\n\n    let minutes = abs((r * 60).rounded(.towardZero))\n\n    let mins = String(format: "%.0f", minutes)\n    let hrs = String(format: "%.0f", q)\n\n    return (hrs, mins)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

注意,如果输入的值为负数,例如-1.75 小时,则商为-1 小时,余数为-0.75 小时。这在数学上是正确的,但显然,如果您要在 UI 中显示这些内容,您可能会希望显示带有负值的小时,但也不想显示分钟。所以我已经完成了abs剩下的部分。

\n

另外,您可能想要向下舍入分钟(这样 1.9999 小时就不会报告 1:60,而是 1:59)。因此,我将余数乘以 60 的乘积向下舍入(为零)。

\n

最重要的是,如果您确实想计算分钟和秒,请随意,但如果只是为了创建字符串表示形式,您可能会考虑让DateComponentFormatter为您执行此操作。它正确处理正值和负值、本地化字符串等。

\n