如何在swift中格式化用户显示(社交网络)的时间间隔?

时间:2021-12-14 21:28:30

I have a time interval, say, 12600, which is equivalent to 3 hours 30 minutes. How could I format any such time interval so that only the highest part of the interval (for example in this case figure, the hours) is kept and have the correct locale abbreviation be appended to the number. For example 10m (10 minutes), 3d (3 days), 1y (1 years).

我有一个时间间隔,比如12600,相当于3小时30分钟。我如何格式化任何这样的时间间隔,以便只保留间隔的最高部分(例如在这种情况下图中的小时),并将正确的区域设置缩写附加到数字上。例如10米(10分钟),3d(3天),1年(1年)。


EDIT: Here are some examples:

编辑:以下是一些例子:

Time interval in: 90000    Whole string: 1d      String out: 1d
Time interval in: 900      Whole string: 15m     String out: 15m
Time interval in: 13500    Whole String: 3h 45m  String out: 4h

As a general rule, apply the normal rounding rules (3.4 rounds down, 3.6 rounds up).

作为一般规则,应用正常的舍入规则(3.4轮向下,3.6轮向上)。

6 个解决方案

#1


24  

Use DateComponentFormatter, available since iOS 8:

使用DateComponentFormatter,自iOS 8起可用:

func format(duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.day, .hour, .minute, .second]
    formatter.unitsStyle = .abbreviated
    formatter.maximumUnitCount = 1

    return formatter.string(from: duration)!
}

for d in [12600.0, 90000.0, 900.0, 13500.0] {
    let str = format(duration: d)
    print("\(d): \(str)")
}

This prints:

12600.0: 4h
90000.0: 1d
900.0: 15m
13500.0: 4h

#2


10  

Swift 3 extension:

Swift 3扩展:

extension TimeInterval {

  func format() -> String? {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.day, .hour, .minute, .second, .nanosecond]
    formatter.unitsStyle = .abbreviated
    formatter.maximumUnitCount = 1
    return formatter.string(from: self)
  }
}

#3


2  

Just in case anyone wants it.. Swift 4

万一有人想要它..斯威夫特4

extension TimeInterval {
func format(using units: NSCalendar.Unit) -> String? {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = units
    formatter.unitsStyle = .abbreviated
    formatter.zeroFormattingBehavior = .pad

    return formatter.string(from: self)
}}

Example usage:

let value:TimeInterval =  12600.0
print("\(value.format(using: [.hour, .minute, .second])!)")

and the result will be:

结果将是:

3h 30m 0s

#4


1  

Take a look at the NSDateComponentsFormatter class. It lets you calculate whatever units you want either using 2 dates or using an NSTimeInterval, and supports different languages and locales automatically. There have been a couple of posts here in SO on the subject.

看一下NSDateComponentsFormatter类。它允许您使用2个日期或使用NSTimeInterval计算您想要的任何单位,并自动支持不同的语言和语言环境。关于这个问题,SO中有几篇帖子。

#5


1  

You can use NSDate and NSCalendar. You can say something like:

您可以使用NSDate和NSCalendar。你可以这样说:

let timeInterval:Double = 12600
let calendar = NSCalendar.currentCalendar()
let date = NSDate(timeInterval: -timeInterval, sinceDate: NSDate())
let components = calendar.components([.Year,.Day,.Hour, .Minute, .Second, .Nanosecond], fromDate: date, toDate: NSDate(), options: [])

let hour = components.hour //3
let minute = components.minute //30

Per duncan's and rmaddy's suggestions use NSDateComponentsFormatter

Per duncan和rmaddy的建议使用NSDateComponentsFormatter

#6


0  

I created a function for you! I hope you like it. And this is super easy to implement and very customizable.

我为你创造了一个功能!我希望你喜欢它。这非常容易实现,并且非常可定制。

func totime(time: Double) -> (String) {

var timex = time

var fancytime: String = "a while"

if time < 61 {
    fancytime = "\(timex)s"
} else if time < 3601 {
    timex = timex/60
    timex = round(timex)
    fancytime = "\(timex)m"
} else if time < 86401 {
    timex = timex/3600
    timex = round(timex)
    fancytime = "\(timex)h"
} else if Double(time) < 3.15576E+07 {
    timex = timex/86400
    timex = round(timex)
    fancytime = "\(timex)d"
} else {
    fancytime = "more than one year"
}

fancytime = fancytime.stringByReplacingOccurrencesOfString(".0", withString: "")

return fancytime
}

Tested, and it works flawlessly:

经过测试,它完美无瑕:

print(totime(90000)) // prints "1d"
print(totime(900)) // prints "15m"
print(totime(13500)) // prints "4h"

Just call it with totime(Double).

只需用totime(Double)调用即可。

#1


24  

Use DateComponentFormatter, available since iOS 8:

使用DateComponentFormatter,自iOS 8起可用:

func format(duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.day, .hour, .minute, .second]
    formatter.unitsStyle = .abbreviated
    formatter.maximumUnitCount = 1

    return formatter.string(from: duration)!
}

for d in [12600.0, 90000.0, 900.0, 13500.0] {
    let str = format(duration: d)
    print("\(d): \(str)")
}

This prints:

12600.0: 4h
90000.0: 1d
900.0: 15m
13500.0: 4h

#2


10  

Swift 3 extension:

Swift 3扩展:

extension TimeInterval {

  func format() -> String? {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.day, .hour, .minute, .second, .nanosecond]
    formatter.unitsStyle = .abbreviated
    formatter.maximumUnitCount = 1
    return formatter.string(from: self)
  }
}

#3


2  

Just in case anyone wants it.. Swift 4

万一有人想要它..斯威夫特4

extension TimeInterval {
func format(using units: NSCalendar.Unit) -> String? {
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = units
    formatter.unitsStyle = .abbreviated
    formatter.zeroFormattingBehavior = .pad

    return formatter.string(from: self)
}}

Example usage:

let value:TimeInterval =  12600.0
print("\(value.format(using: [.hour, .minute, .second])!)")

and the result will be:

结果将是:

3h 30m 0s

#4


1  

Take a look at the NSDateComponentsFormatter class. It lets you calculate whatever units you want either using 2 dates or using an NSTimeInterval, and supports different languages and locales automatically. There have been a couple of posts here in SO on the subject.

看一下NSDateComponentsFormatter类。它允许您使用2个日期或使用NSTimeInterval计算您想要的任何单位,并自动支持不同的语言和语言环境。关于这个问题,SO中有几篇帖子。

#5


1  

You can use NSDate and NSCalendar. You can say something like:

您可以使用NSDate和NSCalendar。你可以这样说:

let timeInterval:Double = 12600
let calendar = NSCalendar.currentCalendar()
let date = NSDate(timeInterval: -timeInterval, sinceDate: NSDate())
let components = calendar.components([.Year,.Day,.Hour, .Minute, .Second, .Nanosecond], fromDate: date, toDate: NSDate(), options: [])

let hour = components.hour //3
let minute = components.minute //30

Per duncan's and rmaddy's suggestions use NSDateComponentsFormatter

Per duncan和rmaddy的建议使用NSDateComponentsFormatter

#6


0  

I created a function for you! I hope you like it. And this is super easy to implement and very customizable.

我为你创造了一个功能!我希望你喜欢它。这非常容易实现,并且非常可定制。

func totime(time: Double) -> (String) {

var timex = time

var fancytime: String = "a while"

if time < 61 {
    fancytime = "\(timex)s"
} else if time < 3601 {
    timex = timex/60
    timex = round(timex)
    fancytime = "\(timex)m"
} else if time < 86401 {
    timex = timex/3600
    timex = round(timex)
    fancytime = "\(timex)h"
} else if Double(time) < 3.15576E+07 {
    timex = timex/86400
    timex = round(timex)
    fancytime = "\(timex)d"
} else {
    fancytime = "more than one year"
}

fancytime = fancytime.stringByReplacingOccurrencesOfString(".0", withString: "")

return fancytime
}

Tested, and it works flawlessly:

经过测试,它完美无瑕:

print(totime(90000)) // prints "1d"
print(totime(900)) // prints "15m"
print(totime(13500)) // prints "4h"

Just call it with totime(Double).

只需用totime(Double)调用即可。