将十进制时间转换为 Swift 中的小时和分钟
Convert decimal time to hours and minutes in Swift
我是编程新手,这是我的第一个程序和问题。我正在尝试编写一个函数,它将简单地将十进制时间转换为小时和分钟。我要删除小时数并将小数点乘以 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
正确答案是 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")
编辑
我知道您想知道什么不适用于您的方法。
这是一个四舍五入的问题,在将它传递给 String(format:)
之前尝试 roundind hours
:
func decimalHoursConv (hours : Double) -> (_hrs:String, mins:String) {
let remainder = hours.truncatingRemainder(dividingBy: 1) * 60
let mins = (String(format: "%.0f", remainder))
let hours = hours.rounded(.towardZero)
let hrs = (String(format: "%.0f", hours))
return (hrs, mins)
}
它给出:
var value = (450.0-185.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "28")
value = (450.0-182.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "29")
value = (450.0-181.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-180.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-179.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-175.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "32")
但仍然
如果您使用 Swift,您 应该 使用 Measurement
func convertToHoursAndMinutes(_ value: Double) -> DateComponents {
let unitMeasurement = Measurement(value: value, unit: UnitDuration.minutes)
let hours = unitMeasurement.converted(to: .hours).value
let decimalPart = hours.truncatingRemainder(dividingBy: 1)
let decimalPartMeasurement = Measurement(value: decimalPart, unit: UnitDuration.hours)
let decimalPartMeasurementInMinutes = decimalPartMeasurement.converted(to: .minutes)
let minutes = decimalPartMeasurementInMinutes.value.rounded(.toNearestOrEven)
return DateComponents(hour: Int(hours), minute: Int(minutes))
}
用法:
var value = (450.0-185.0)/3 // 88.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 28 isLeapMonth: false
value = (450.0-182.0)/3 // 89.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 29 isLeapMonth: false
value = (450.0-181.0)/3 // 89.66666666666667
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-180.0)/3 // 90
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-179.0)/3 // 90.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-175.0)/3 // 91.66666666666667
convertToHoursAndMinutes(value) // hour: 1 minute: 32 isLeapMonth: false
请注意,如果愿意,您始终可以使用元组代替 DateComponents
。
String
格式化程序循环 up.
您可以在 Double
上使用 .rounded(.down)
将它们四舍五入。 (或您需要的其他规则)
let number = (179.0/60.0) // 2.983333333333333
String(format: "%.0f", number) // returns 3
number.rounded(.up) // returns 3
number.rounded(.down) // returns 2
首先你应该构建你的数据。接下来,如果您不打算显示分数,则不需要将您的值格式化为 Double。所以你可以简单地将你的双精度转换为整数。
struct FlightPlan {
let plannedStartFuel: Double
let minimumLandAllowance: Double
}
extension FlightPlan {
var mlaTime: (hours: Int, minutes: Int) {
let hours = (plannedStartFuel - minimumLandAllowance) / 180
return (Int(hours), Int(modf(hours).1 * 60))
}
}
并且在向用户显示时间时应该使用 DateComponentsFormatter
:
extension Formatter {
static let time: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.calendar?.locale = .init(identifier: "en_US_POSIX")
formatter.unitsStyle = .brief
formatter.allowedUnits = [.hour,.minute]
return formatter
}()
}
extension FlightPlan {
var mlaTimeDescrition: String {
return "Flight Time To MLA = " + Formatter.time.string(from: .init(hour: mlaTime.hours, minute: mlaTime.minutes))!
}
}
let flightPlan = FlightPlan(plannedStartFuel: 450,
minimumLandAllowance: 180)
flightPlan.mlaTime // (hours 1, minutes 30)
flightPlan.mlaTime.hours // 1
flightPlan.mlaTime.minutes // 30
flightPlan.mlaTimeDescrition // "Flight Time To MLA = 1hr 30min"
我可能建议根本不要计算小时和分钟,而是让 DateComponentsFormatter
这样做,为您创建最终的字符串。
例如:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
然后向格式化程序提供以秒为单位的经过时间(TimeInterval
,这只是 Double
的别名):
let remaining: TimeInterval = 90 * 60 // e.g. 90 minutes represented in seconds
if let result = formatter.string(from: remaining) {
print(result)
}
在英语设备上,将产生:
1 hour, 30 minutes
这种方法的优点在于,它不仅让您摆脱了自己手动计算小时和分钟的工作,而且结果很容易本地化。因此,如果您着手本地化您的应用程序,此字符串也将自动为您本地化,无需您做进一步的工作。例如,如果您将德语添加到您的应用程序本地化中,那么美国用户仍会看到上面的内容,但在德国设备上,它将产生:
1 Stunde und 30 Minuten
如果你想让它说出剩余时间,设置includesTimeRemainingPhrase
:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.includesTimeRemainingPhrase = true
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
这将产生:
1 hour, 30 minutes remaining
如果你想要一种“hh:mm”的表示形式:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
将产生:
01:30
底线,如果你真的想计算分钟和秒,请随意,但如果它只是为了创建一个字符串表示,让 DateComponentFormatter
为你做这件事。
我是编程新手,这是我的第一个程序和问题。我正在尝试编写一个函数,它将简单地将十进制时间转换为小时和分钟。我要删除小时数并将小数点乘以 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
正确答案是 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")
编辑
我知道您想知道什么不适用于您的方法。
这是一个四舍五入的问题,在将它传递给 String(format:)
之前尝试 roundind hours
:
func decimalHoursConv (hours : Double) -> (_hrs:String, mins:String) {
let remainder = hours.truncatingRemainder(dividingBy: 1) * 60
let mins = (String(format: "%.0f", remainder))
let hours = hours.rounded(.towardZero)
let hrs = (String(format: "%.0f", hours))
return (hrs, mins)
}
它给出:
var value = (450.0-185.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "28")
value = (450.0-182.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "29")
value = (450.0-181.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-180.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-179.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-175.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "32")
但仍然 如果您使用 Swift,您 应该 使用 Measurement
func convertToHoursAndMinutes(_ value: Double) -> DateComponents {
let unitMeasurement = Measurement(value: value, unit: UnitDuration.minutes)
let hours = unitMeasurement.converted(to: .hours).value
let decimalPart = hours.truncatingRemainder(dividingBy: 1)
let decimalPartMeasurement = Measurement(value: decimalPart, unit: UnitDuration.hours)
let decimalPartMeasurementInMinutes = decimalPartMeasurement.converted(to: .minutes)
let minutes = decimalPartMeasurementInMinutes.value.rounded(.toNearestOrEven)
return DateComponents(hour: Int(hours), minute: Int(minutes))
}
用法:
var value = (450.0-185.0)/3 // 88.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 28 isLeapMonth: false
value = (450.0-182.0)/3 // 89.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 29 isLeapMonth: false
value = (450.0-181.0)/3 // 89.66666666666667
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-180.0)/3 // 90
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-179.0)/3 // 90.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-175.0)/3 // 91.66666666666667
convertToHoursAndMinutes(value) // hour: 1 minute: 32 isLeapMonth: false
请注意,如果愿意,您始终可以使用元组代替 DateComponents
。
String
格式化程序循环 up.
您可以在 Double
上使用 .rounded(.down)
将它们四舍五入。 (或您需要的其他规则)
let number = (179.0/60.0) // 2.983333333333333
String(format: "%.0f", number) // returns 3
number.rounded(.up) // returns 3
number.rounded(.down) // returns 2
首先你应该构建你的数据。接下来,如果您不打算显示分数,则不需要将您的值格式化为 Double。所以你可以简单地将你的双精度转换为整数。
struct FlightPlan {
let plannedStartFuel: Double
let minimumLandAllowance: Double
}
extension FlightPlan {
var mlaTime: (hours: Int, minutes: Int) {
let hours = (plannedStartFuel - minimumLandAllowance) / 180
return (Int(hours), Int(modf(hours).1 * 60))
}
}
并且在向用户显示时间时应该使用 DateComponentsFormatter
:
extension Formatter {
static let time: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.calendar?.locale = .init(identifier: "en_US_POSIX")
formatter.unitsStyle = .brief
formatter.allowedUnits = [.hour,.minute]
return formatter
}()
}
extension FlightPlan {
var mlaTimeDescrition: String {
return "Flight Time To MLA = " + Formatter.time.string(from: .init(hour: mlaTime.hours, minute: mlaTime.minutes))!
}
}
let flightPlan = FlightPlan(plannedStartFuel: 450,
minimumLandAllowance: 180)
flightPlan.mlaTime // (hours 1, minutes 30)
flightPlan.mlaTime.hours // 1
flightPlan.mlaTime.minutes // 30
flightPlan.mlaTimeDescrition // "Flight Time To MLA = 1hr 30min"
我可能建议根本不要计算小时和分钟,而是让 DateComponentsFormatter
这样做,为您创建最终的字符串。
例如:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
然后向格式化程序提供以秒为单位的经过时间(TimeInterval
,这只是 Double
的别名):
let remaining: TimeInterval = 90 * 60 // e.g. 90 minutes represented in seconds
if let result = formatter.string(from: remaining) {
print(result)
}
在英语设备上,将产生:
1 hour, 30 minutes
这种方法的优点在于,它不仅让您摆脱了自己手动计算小时和分钟的工作,而且结果很容易本地化。因此,如果您着手本地化您的应用程序,此字符串也将自动为您本地化,无需您做进一步的工作。例如,如果您将德语添加到您的应用程序本地化中,那么美国用户仍会看到上面的内容,但在德国设备上,它将产生:
1 Stunde und 30 Minuten
如果你想让它说出剩余时间,设置includesTimeRemainingPhrase
:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.includesTimeRemainingPhrase = true
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
这将产生:
1 hour, 30 minutes remaining
如果你想要一种“hh:mm”的表示形式:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
将产生:
01:30
底线,如果你真的想计算分钟和秒,请随意,但如果它只是为了创建一个字符串表示,让 DateComponentFormatter
为你做这件事。