如何从 iOS swift 中的日期获取 1 小时前?

Posted

技术标签:

【中文标题】如何从 iOS swift 中的日期获取 1 小时前?【英文标题】:How to get 1 hour ago from a date in iOS swift? 【发布时间】:2014-12-02 14:19:23 【问题描述】:

我一直在研究,但我找不到我的问题的确切解决方案。我一直试图从一个日期开始 1 小时前。我怎样才能快速做到这一点?

【问题讨论】:

【参考方案1】:

对于涉及 NSDate 的正确计算,考虑到不同日历的所有边缘情况(例如在夏令时之间切换),您应该使用 NSCalendar 类:

Swift 3+

let earlyDate = Calendar.current.date(
  byAdding: .hour, 
  value: -1, 
  to: Date())

老年人

// Get the date that was 1hr before now
let earlyDate = NSCalendar.currentCalendar().dateByAddingUnit(
       .Hour,
       value: -1, 
       toDate: NSDate(),
       options: [])

【讨论】:

WrapComponents 有什么用? .WrapComponents 表示如果增加一个小时会使您超过午夜,则不要增加日期。我认为使用options: [] 更有意义,就像线程底部的 Deepak 的回答一样。 对于 Swift3 ... let changedDate = userCalendar.date(byAdding: .hour, value: -1, to: now)【参考方案2】:

使用此方法并粘贴到您的助手类中。

为 Swift 3 和 Xcode 8.3 更新

class func timeAgoSinceDate(_ date:Date,currentDate:Date, numericDates:Bool) -> String 
    let calendar = Calendar.current
    let now = currentDate
    let earliest = (now as NSDate).earlierDate(date)
    let latest = (earliest == now) ? date : now
    let components:DateComponents = (calendar as NSCalendar).components([NSCalendar.Unit.minute , NSCalendar.Unit.hour , NSCalendar.Unit.day , NSCalendar.Unit.weekOfYear , NSCalendar.Unit.month , NSCalendar.Unit.year , NSCalendar.Unit.second], from: earliest, to: latest, options: NSCalendar.Options())
    
    if (components.year! >= 2) 
        return "\(components.year!) years ago"
     else if (components.year! >= 1)
        if (numericDates)
            return "1 year ago"
         else 
            return "Last year"
        
     else if (components.month! >= 2) 
        return "\(components.month!) months ago"
     else if (components.month! >= 1)
        if (numericDates)
            return "1 month ago"
         else 
            return "Last month"
        
     else if (components.weekOfYear! >= 2) 
        return "\(components.weekOfYear!) weeks ago"
     else if (components.weekOfYear! >= 1)
        if (numericDates)
            return "1 week ago"
         else 
            return "Last week"
        
     else if (components.day! >= 2) 
        return "\(components.day!) days ago"
     else if (components.day! >= 1)
        if (numericDates)
            return "1 day ago"
         else 
            return "Yesterday"
        
     else if (components.hour! >= 2) 
        return "\(components.hour!) hours ago"
     else if (components.hour! >= 1)
        if (numericDates)
            return "1 hour ago"
         else 
            return "An hour ago"
        
     else if (components.minute! >= 2) 
        return "\(components.minute!) minutes ago"
     else if (components.minute! >= 1)
        if (numericDates)
            return "1 minute ago"
         else 
            return "A minute ago"
        
     else if (components.second! >= 3) 
        return "\(components.second!) seconds ago"
     else 
        return "Just now"
    
    

此方法的使用:

var timeAgo:String=AppHelper.timeAgoSinceDate(date, numericDates: true)
Print("\(timeAgo)")   // Ex- 1 hour ago

【讨论】:

非常感谢,真的很有用! 非常有用的答案! 这里是 NSDate 类的扩展:gist.github.com/vikdenic/988d6f3920b7b7950d40 关于真正的 Swift 3(+) 摆脱 NS... 类的建议:let earliest = min(now, date)let latest = max(now, date)let components = calendar.dateComponents([.minute , .hour , .day , .weekOfYear , .month , .year , .second], from: earliest, to: latest) 非常感谢.... :) 这个功能对我真的很有用【参考方案3】:

请阅读NSDate 类参考。

let oneHourAgo = NSDate.dateWithTimeIntervalSinceNow(-3600)

应该这样做。

或者,对于任何NSDate 对象:

let oneHourBack = myDate.dateByAddingTimeInterval(-3600)

斯威夫特 4:

let oneHourAgo = NSDate(timeIntervalSinceNow: -3600)

【讨论】:

感谢您的回答。问题消失了:) 前者的新语法为:NSDate(timeIntervalSinceNow: -3600)【参考方案4】:

根据您的需要,您可以选择以下 3 种 Swift 5 方法之一从 Date 实例获取一小时前。


1。 date(byAdding:value:to:wrappingComponents:)

Calendar 有一个名为date(byAdding:value:to:wrappingComponents:) 的方法。 date(byAdding:value:to:wrappingComponents:) 有以下声明:

func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = default) -> Date?

返回一个新的Date,表示通过将特定组件的数量与给定日期相加计算得出的日期。

下面的 Playground 代码显示了如何使用它:

import Foundation

let now = Date()
let oneHourAgo = Calendar.current.date(byAdding: .hour, value: -1, to: now)

print(now) // 2016-12-19 21:52:04 +0000
print(String(describing: oneHourAgo)) // Optional(2016-12-19 20:52:04 +0000)

2。 date(byAdding:to:wrappingComponents:)

Calendar 有一个名为date(byAdding:to:wrappingComponents:) 的方法。 date(byAdding:value:to:wrappingComponents:) 有以下声明:

func date(byAdding components: DateComponents, to date: Date, wrappingComponents: Bool = default) -> Date?

返回一个新的Date,表示通过将组件添加到给定日期计算得出的日期。

下面的 Playground 代码显示了如何使用它:

import Foundation

let now = Date()

var components = DateComponents()
components.hour = -1
let oneHourAgo = Calendar.current.date(byAdding: components, to: now)

print(now) // 2016-12-19 21:52:04 +0000
print(String(describing: oneHourAgo)) // Optional(2016-12-19 20:52:04 +0000)

替代方案:

import Foundation

// Get the date that was 1hr before now
let now = Date()

let components = DateComponents(hour: -1)
let oneHourAgo = Calendar.current.date(byAdding: components, to: now)

print(now) // 2016-12-19 21:52:04 +0000
print(String(describing: oneHourAgo)) // Optional(2016-12-19 20:52:04 +0000)

3。 addingTimeInterval(_:)(慎用)

Date 有一个名为addingTimeInterval(_:) 的方法。 addingTimeInterval(_:) 有以下声明:

func addingTimeInterval(_ timeInterval: TimeInterval) -> Date

通过将TimeInterval 添加到此Date 来返回新的Date

请注意,此方法带有警告:

这只会调整绝对值。如果您想添加诸如小时、天、月之类的日历概念,则必须使用Calendar。这将考虑到复杂性,例如夏令时、不同天数的月份等等。

下面的 Playground 代码显示了如何使用它:

import Foundation

let now = Date()
let oneHourAgo = now.addingTimeInterval(-3600)

print(now) // 2016-12-19 21:52:04 +0000
print(oneHourAgo) // 2016-12-19 20:52:04 +0000

【讨论】:

选项一,date(byAdding:value:to:wrappingComponents:) 似乎是最合适/最简单的选择。它允许您将单个日期组件值添加到日期。【参考方案5】:

如果你使用NSDate,你可以这样做:

let date = NSDate()
date.dateByAddingTimeInterval(-3600)

它将date 对象更改为“1 小时前”。

【讨论】:

【参考方案6】:

Swift3:

let now = Date()
let tempCalendar = Calendar.current
let alteredDate = tempCalendar.date(byAdding: .hour, value: -1, to: now)

【讨论】:

【参考方案7】:

我通过创建 Date 的扩展来实现时间前的功能。如下:

extension Date 
 // Returns the number of years 
 func yearsCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
 
 // Returns the number of months
 func monthsCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
 
 // Returns the number of weeks
 func weeksCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
 
 // Returns the number of days
 func daysCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
 
 // Returns the number of hours
 func hoursCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
 
 // Returns the number of minutes
func minutesCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
 
 // Returns the number of seconds
 func secondsCount(from date: Date) -> Int 
    return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
 
 // Returns time ago by checking if the time differences between two dates are in year or months or weeks or days or hours or minutes or seconds
 func timeAgo(from date: Date) -> String 
    if yearsCount(from: date)   > 0  return "\(yearsCount(from: date))years ago"   
    if monthsCount(from: date)  > 0  return "\(monthsCount(from: date))months ago"  
    if weeksCount(from: date)   > 0  return "\(weeksCount(from: date))weeks ago"   
    if daysCount(from: date)    > 0  return "\(daysCount(from: date))days ago"    
    if hoursCount(from: date)   > 0  return "\(hoursCount(from: date))hours ago"   
    if minutesCount(from: date) > 0  return "\(minutesCount(from: date))minutes ago" 
    if secondsCount(from: date) > 0  return "\(secondsCount(from: date))seconds ago" 
    return ""
  

然后我通过计算当前日期和指定日期之间的差异来获得时间:

   let timeAgo = Date().timeAgo(from: sender.date)

【讨论】:

【参考方案8】:

对于 Swift 2:

extension NSDate 
    func after(value: Int, calendarUnit:NSCalendarUnit) -> NSDate 
        return calendar.dateByAddingUnit(calendarUnit, value: value, toDate: self, options: [])!
    

使用方法:

let lastHour = NSDate().after(-1, calendarUnit: .Hour)

【讨论】:

【参考方案9】:

你也可以使用运算符

let date = Date()
let anHourAgo = date - TimeInterval(3600.0)

苹果文档: https://developer.apple.com/documentation/foundation/date/2293436

【讨论】:

【参考方案10】:

这适用于 ios 13 / Swift 5。感谢 Sourabh Sharma

func timeAgoSinceNow(numericDates: Bool = true) -> String 
    let calendar = Calendar.current
    let now = Date()
    let earliest = (now as NSDate).earlierDate(self)
    let latest = (earliest == now) ? self : now
    let components: DateComponents = (calendar as NSCalendar).components([NSCalendar.Unit.minute,
                                                                          NSCalendar.Unit.hour,
                                                                          NSCalendar.Unit.day,
                                                                          NSCalendar.Unit.weekOfYear,
                                                                          NSCalendar.Unit.month,
                                                                          NSCalendar.Unit.year,
                                                                          NSCalendar.Unit.second],
                                                                         from: earliest,
                                                                         to: latest,
                                                                         options: NSCalendar.Options())

    guard
        let year = components.year,
        let month = components.month,
        let weekOfYear = components.weekOfYear,
        let day = components.day,
        let hour = components.hour,
        let minute = components.minute,
        let second = components.second
    else  return "A while ago"

    if year >= 1 
        return year >= 2 ? "\(year) years ago" : numericDates ? "1 year ago" : "Last year"
     else if month >= 1 
        return month >= 2 ? "\(month) months ago" : numericDates ? "1 month ago" : "Last month"
     else if weekOfYear >= 1 
        return weekOfYear >= 2 ? "\(weekOfYear) weeks ago" : numericDates ? "1 week ago" : "Last week"
     else if day >= 1 
        return day >= 2 ? "\(day) days ago" : numericDates ? "1 day ago" : "Yesterday"
     else if hour >= 1 
        return hour >= 2 ? "\(hour) hours ago" : numericDates ? "1 hour ago" : "An hour ago"
     else if minute >= 1 
        return minute >= 2 ? "\(minute) minutes ago" : numericDates ? "1 minute ago" : "A minute ago"
     else 
        return second >= 3 ? "\(second) seconds ago" : "Just now"
    

用法:

var date = Date() // Or any date you wish to convert to text
print("\(date.timeAgoSinceNow())") // "Just Now"

【讨论】:

【参考方案11】:
Calendar.current.date( byAdding: .hour, value: -1, to: Date())

【讨论】:

请考虑将答案的相关部分格式化为代码。 它看起来对之前提供的其他答案没有任何改进【参考方案12】:

在swift 5中你可以使用

      let earlyDate = Calendar.current.date( byAdding: .hour, value: -1, to: Date())
      let df = DateFormatter()
      df.dateFormat = "yyyy-MM-dd HH:mm:ss"
      let dateString = df.string(from: earlyDate!)

输出会像下面这样

Current DateTime--> 2019-12-20 09:40:08
One Hour Previous Date Time--> 2019-12-20 08:40:08

【讨论】:

【参考方案13】:

详情

Xcode 11.4 (11E146)、Swift 5.2

解决方案

import Foundation

extension Date 

    typealias Component = (value: Int, type: Calendar.Component)

    init?(bySubtracting components: Component..., calendar: Calendar = Calendar.current, from date: Date) 
        guard let date = date.subtract(components, calendar: calendar) else  return nil 
        self = date
    

    func subtract(_ components: Component..., calendar: Calendar = Calendar.current) -> Date? 
        subtract(components, calendar: calendar)
    

    func subtract(_ components: [Component], calendar: Calendar = Calendar.current) -> Date? 
        components.reduce(self)  (result, component) -> Date? in
            guard let date = result else  return nil 
            return calendar.date(byAdding: component.type, value: (-1)*component.value, to: date)
        
    

    static func beforeNow(difference component: Component..., calendar: Calendar = Calendar.current) -> Date? 
        Date().subtract(component, calendar: calendar)
    

    static func beforeNow(difference component: [Component], calendar: Calendar = Calendar.current) -> Date? 
        Date().subtract(component, calendar: calendar)
    


extension Date 
    static func - (date: Date, component: Date.Component) -> Date?  date.subtract(component, calendar: Calendar.current) 
    static func -= (date: inout Date, component: Date.Component) 
        guard let newDate = date.subtract(component, calendar: Calendar.current) else  return 
        date = newDate
    

用法

var currentDate = Date()
let date1 = Date(bySubtracting: (30, .day), from: currentDate)

let date2 = Date().subtract((30, .day))

let date3 = Date().subtract([(1, .minute), (2, .hour), (3, .day), (4, .month)])

let component = Date.Component(value: 1, type: .day)
let date4 = Date.beforeNow(difference: component)

let date5 = Date.beforeNow(difference: (1, .minute), (2, .hour), (3, .day), (4, .month))

let date6 = Date.beforeNow(difference: [(1, .minute), (2, .hour), (3, .day), (4, .month)])

let date7 = currentDate - (1, .day)

currentDate -= Date.Component(value: 1, type: .day)

更多

Get components (hours, months, days...) from date Compare days by components Convert date to formated string date

【讨论】:

【参考方案14】:
let now = Date()
let nowMinusTwoAndAHalfHours = now - 2.5*60*60

print(now)
print(nowMinusTwoAndAHalfHours)

【讨论】:

以上是关于如何从 iOS swift 中的日期获取 1 小时前?的主要内容,如果未能解决你的问题,请参考以下文章

swift - 如何将日期从上午/下午转换为 24 小时格式

如何从 db2 中的选定日期获取接下来 24 小时的所有数据?

如何从swift中的时间戳获取日期格式

从 NSDatePicker 获取小时和分钟 - Swift

iOS Swift 3 - UIDatePicker

iOS:从 NSDate 获取本地化小时