web-dev-qa-db-ja.com

Swift時間を前に変換

Swift5では、RelativeDateTimeFormatter

Swift5より前:


私は時々前に変換しようとしています、私がしたいのは:

1〜15秒の間、「Just now」と表示されます

60分から119分までは「1時間前」と表示されます

24時間から47時間までは「昨日」と表示されます

7日から7日23時間までは、「1週間前」と表示されます

私が間違っているかどうか、私のためにそれを修正するのを遠慮しないかどうか、私のカウントについてはわかりません

これがコードです

    extension NSDate {

    struct Date {
        static let timeFormatter: NSDateFormatter = {
            let df = NSDateFormatter()
            df.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
            df.dateFormat = "h:mm a"
            return df
            }()
    }
    var time: String { return Date.timeFormatter.stringFromDate(self) }

    var year:    Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Year,   fromDate: self) }
    var month:   Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Month,  fromDate: self) }
    var day:     Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Day,    fromDate: self) }
    var hour:     Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Hour,    fromDate: self) }
    var minute:     Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Minute,    fromDate: self) }
    var second:     Int { return NSCalendar.autoupdatingCurrentCalendar().component(.Second,    fromDate: self) }


    struct DateComponents {
        static let formatter: NSDateComponentsFormatter = {
            let dcFormatter = NSDateComponentsFormatter()
            dcFormatter.calendar = NSCalendar(identifier: NSCalendarIdentifierISO8601)!
            dcFormatter.unitsStyle = .Full
            dcFormatter.maximumUnitCount = 1
            dcFormatter.zeroFormattingBehavior = .Default
            dcFormatter.allowsFractionalUnits = false
            dcFormatter.allowedUnits = [.Year, .Month, .Weekday, .Day, .Hour, .Minute, .Second]
            return dcFormatter
            }()
    }

    var elapsedTime: String {


        if isecond(NSDate()) {
            return "Just now"

        }

        if ishour(NSDate()) {
           return "an hour ago"

        }
        if isyesterday(NSDate()) {
            return "Yesterday"
        }
        if isweek(NSDate()) {

            return "a week ago"
        }




        return (DateComponents.formatter.stringFromTimeInterval(NSDate().timeIntervalSinceDate(self)) ?? "") + " ago"
    }
    func isyesterday(date: NSDate) -> Bool {
        return  NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.yesterday)
    }
    var yesterday: NSDate {
        return  NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: day-1, hour: 0, minute: 0, second: 0, nanosecond: 0)!
    }



    func isweek(date: NSDate) -> Bool {
        return  NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.weekago)
    }
    var weekago: NSDate {
        return  NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: day-7, hour: 0, minute: 0, second: 0, nanosecond: 0)!
    }

    func isecond(date: NSDate) -> Bool {
        return  NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.secondsago)
    }
    var secondsago: NSDate {
        return  NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: 0, hour: 0, minute: 0, second: second-15, nanosecond: 0)!
    }

    func ishour(date: NSDate) -> Bool {
        return  NSCalendar.autoupdatingCurrentCalendar().isDate(self, inSameDayAsDate: date.hourago)
    }
    var hourago: NSDate {
        return  NSCalendar.autoupdatingCurrentCalendar().dateWithEra(1, year: year, month: month, day: 0, hour: hour-1, minute: minute-1, second: 0, nanosecond: 0)!
    }
}

ここに私が私のアプリで得たもの: enter image description here

「1時間前」、「たった今」などの引用が表示されず、「昨日」のみで、7日から23時間のみかどうかはわかりません。

そして、これが私の最初の質問リンクです: Swift Created to Parse createdAt time to time ago?

コードの@Leo Dabusのおかげで、コードの修正を手伝ってください。

21
Salah

SwiftのTruongkyの回答を更新します。

extension Date {

func getElapsedInterval() -> String {

    let interval = Calendar.current.dateComponents([.year, .month, .day], from: self, to: Date())

    if let year = interval.year, year > 0 {
        return year == 1 ? "\(year)" + " " + "year ago" :
            "\(year)" + " " + "years ago"
    } else if let month = interval.month, month > 0 {
        return month == 1 ? "\(month)" + " " + "month ago" :
            "\(month)" + " " + "months ago"
    } else if let day = interval.day, day > 0 {
        return day == 1 ? "\(day)" + " " + "day ago" :
            "\(day)" + " " + "days ago"
    } else {
        return "a moment ago"

    }

}
}

英語のみではなくローカライズ可能な応答を希望する場合、このコードは機能します

extension Date {
func getElapsedInterval() -> String {

    var calendar = Calendar.current
    calendar.locale = Locale(identifier: Bundle.main.preferredLocalizations[0]) 
// IF THE USER HAVE THE PHONE IN SPANISH BUT YOUR APP ONLY SUPPORTS I.E. ENGLISH AND GERMAN
// WE SHOULD CHANGE THE LOCALE OF THE FORMATTER TO THE PREFERRED ONE 
// (IS THE LOCALE THAT THE USER IS SEEING THE APP), IF NOT, THIS ELAPSED TIME 
// IS GOING TO APPEAR IN SPANISH

    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .full
    formatter.maximumUnitCount = 1
    formatter.calendar = calendar

    var dateString: String?

    let interval = calendar.dateComponents([.year, .month, .weekOfYear, .day], from: self, to: Date())

    if let year = interval.year, year > 0 {
        formatter.allowedUnits = [.year] //2 years
    } else if let month = interval.month, month > 0 {
        formatter.allowedUnits = [.month] //1 month
    } else if let week = interval.weekOfYear, week > 0 {
        formatter.allowedUnits = [.weekOfMonth] //3 weeks
    } else if let day = interval.day, day > 0 {
        formatter.allowedUnits = [.day] // 6 days
    } else {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: Bundle.main.preferredLocalizations[0]) //--> IF THE USER HAVE THE PHONE IN SPANISH BUT YOUR APP ONLY SUPPORTS I.E. ENGLISH AND GERMAN WE SHOULD CHANGE THE LOCALE OF THE FORMATTER TO THE PREFERRED ONE (IS THE LOCALE THAT THE USER IS SEEING THE APP), IF NOT, THIS ELAPSED TIME IS GOING TO APPEAR IN SPANISH
        dateFormatter.dateStyle = .medium
        dateFormatter.doesRelativeDateFormatting = true

        dateString = dateFormatter.string(from: self) // IS GOING TO SHOW 'TODAY'
    }

    if dateString == nil {
        dateString = formatter.string(from: self, to: Date())
    }

    return dateString!
}
28
Sonia Casas

Swift 4+バージョン

extension Date {

    func timeAgoSinceDate() -> String {

        // From Time
        let fromDate = self

        // To Time
        let toDate = Date()

        // Estimation
        // Year
        if let interval = Calendar.current.dateComponents([.year], from: fromDate, to: toDate).year, interval > 0  {

            return interval == 1 ? "\(interval)" + " " + "year ago" : "\(interval)" + " " + "years ago"
        }

        // Month
        if let interval = Calendar.current.dateComponents([.month], from: fromDate, to: toDate).month, interval > 0  {

            return interval == 1 ? "\(interval)" + " " + "month ago" : "\(interval)" + " " + "months ago"
        }

        // Day
        if let interval = Calendar.current.dateComponents([.day], from: fromDate, to: toDate).day, interval > 0  {

            return interval == 1 ? "\(interval)" + " " + "day ago" : "\(interval)" + " " + "days ago"
        }

        // Hours
        if let interval = Calendar.current.dateComponents([.hour], from: fromDate, to: toDate).hour, interval > 0 {

            return interval == 1 ? "\(interval)" + " " + "hour ago" : "\(interval)" + " " + "hours ago"
        }

        // Minute
        if let interval = Calendar.current.dateComponents([.minute], from: fromDate, to: toDate).minute, interval > 0 {

            return interval == 1 ? "\(interval)" + " " + "minute ago" : "\(interval)" + " " + "minutes ago"
        }

        return "a moment ago"
    }
}

使用法

yourDate.timeAgoSinceDate()
17

必要に応じてテキストを変更します。

extension NSDate {

    func getElapsedInterval() -> String {

        var interval = NSCalendar.currentCalendar().components(.Year, fromDate: self, toDate: NSDate(), options: []).year

        if interval > 0 {
            return interval == 1 ? "\(interval)" + " " + "year" :
            "\(interval)" + " " + "years"
        }

        interval = NSCalendar.currentCalendar().components(.Month, fromDate: self, toDate: NSDate(), options: []).month
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " " + "month" :
            "\(interval)" + " " + "months"
        }

        interval = NSCalendar.currentCalendar().components(.Day, fromDate: self, toDate: NSDate(), options: []).day
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " " + "day" :
            "\(interval)" + " " + "days"
        }

        interval = NSCalendar.currentCalendar().components(.Hour, fromDate: self, toDate: NSDate(), options: []).hour
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " " + "hour" :
            "\(interval)" + " " + "hours"
        }

        interval = NSCalendar.currentCalendar().components(.Minute, fromDate: self, toDate: NSDate(), options: []).minute
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " " + "minute" :
            "\(interval)" + " " + "minutes"
        }

        return "a moment ago"
    }
}
12
truongky

Swift 3バージョンの truongkyのコード

extension Date {

    var timeAgoSinceNow: String {
        return getTimeAgoSinceNow()
    }

    private func getTimeAgoSinceNow() -> String {

        var interval = Calendar.current.dateComponents([.year], from: self, to: Date()).year!
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " year" : "\(interval)" + " years"
        }

        interval = Calendar.current.dateComponents([.month], from: self, to: Date()).month!
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " month" : "\(interval)" + " months"
        }

        interval = Calendar.current.dateComponents([.day], from: self, to: Date()).day!
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " day" : "\(interval)" + " days"
        }

        interval = Calendar.current.dateComponents([.hour], from: self, to: Date()).hour!
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " hour" : "\(interval)" + " hours"
        }

        interval = Calendar.current.dateComponents([.minute], from: self, to: Date()).minute!
        if interval > 0 {
            return interval == 1 ? "\(interval)" + " minute" : "\(interval)" + " minutes"
        }

        return "a moment ago"
    }
}
6
rgkobashi

Swift 5はRelativeDateTimeFormatterを使用し、

let formatter = RelativeDateTimeFormatter()

formatter.localizedString(from: DateComponents(day: -1)) // "1 day ago"
formatter.localizedString(from: DateComponents(hour: 2)) // "in 2 hours"
formatter.localizedString(from: DateComponents(minute: 45)) // "in 45 minutes"

dateTimeStyleを設定し、ローカライズされた直示ステートメントを取得します。 -

formatter.dateTimeStyle = .named 
formatter.localizedString(from: DateComponents(day: -1)) // "yesterday"
5
rustylepord

私のニーズは、「今」または「x前」のどちらかで単純です

IOS 8以降は(NS)DateComponentsFormatterを使用できます

func getElapsedInterval() -> String {

    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.minute, .hour, .day, .month, .year]
    formatter.unitsStyle = .abbreviated
    formatter.zeroFormattingBehavior = .dropAll
    formatter.maximumUnitCount = 1

    var dateString: String?

    if self.timeIntervalSince(Date()) > -60*5 {
        dateString = NSLocalizedString("now", comment: "")
    } else {
        dateString = String.init(format: NSLocalizedString("%@ ago", comment: ""), locale: .current, formatter.string(from: self, to: Date())!)
    }

    return dateString ?? ""
}

例えば.

var date = Date.init(timeIntervalSinceNow: -60)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*10)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60*24)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60*24*30)
print(date.getElapsedInterval())
date = Date.init(timeIntervalSinceNow: -60*60*24*31*12)
print(date.getElapsedInterval())


10分前
1時間前
1日前
1か月前
1年前

2
Rand

NSDateの代わりに日付を使用: Answer takeing from:

func timeAgoSinceDate(_ date:Date, numericDates:Bool = false) -> String {
    let calendar = NSCalendar.current
    let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfYear, .month, .year, .second]
    let now = Date()
    let earliest = now < date ? now : date
    let latest = (earliest == now) ? date : now
    let components = calendar.dateComponents(unitFlags, from: earliest,  to: latest)

    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 createdDate : String = "123232323" //time stamp
var createdDataDisplayString: String {
    let date = Date(timeIntervalSince1970: Double(self.createdDate)!).timeAgoSinceDate(numericDates: true)
    return "\(date)"
}
print(self.createdDataDisplayString)
2
FARAZ

Swift 4.1。関数paramに日付を渡すと、関数は過去の時間を返します。

func getPastTime(for date : Date) -> String {

    var secondsAgo = Int(Date().timeIntervalSince(date))
    if secondsAgo < 0 {
        secondsAgo = secondsAgo * (-1)
    }

    let minute = 60
    let hour = 60 * minute
    let day = 24 * hour
    let week = 7 * day

    if secondsAgo < minute  {
        if secondsAgo < 2{
            return "just now"
        }else{
            return "\(secondsAgo) secs ago"
        }
    } else if secondsAgo < hour {
        let min = secondsAgo/minute
        if min == 1{
            return "\(min) min ago"
        }else{
            return "\(min) mins ago"
        }
    } else if secondsAgo < day {
        let hr = secondsAgo/hour
        if hr == 1{
            return "\(hr) hr ago"
        } else {
            return "\(hr) hrs ago"
        }
    } else if secondsAgo < week {
        let day = secondsAgo/day
        if day == 1{
            return "\(day) day ago"
        }else{
            return "\(day) days ago"
        }
    } else {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM dd, hh:mm a"
        formatter.locale = Locale(identifier: "en_US")
        let strDate: String = formatter.string(from: date)
        return strDate
    }
}
2
Gurjinder Singh

この日付拡張子をヘルパークラスまたはSwift file。Swift 4.2のいずれかに追加する必要があります。Swiftで必要な場合コメント行のコメントを外して、次の行をコメント化します。

次のようにメソッドを呼び出します。

 let dateText = Date().offsetFrom(date: yourDate!)

yourDateは変更される日付です

////MARK: *************** Extension Date ***************
 extension Date{


func convertToString(validDateFormatter:String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = validDateFormatter //"dd MMM yyyy" //yyyy-mm-dd hh:mm
    //return dateFormatter.stringFromDate(self)
    return dateFormatter.string(from: self as Date)

}

func yearsFrom(date:Date) -> Int{
    //        return NSCalendar.currentCalendar.components(.Year, fromDate: date, toDate: self, options: []).year
    //        let calendar = NSCalendar.current

    //        let components = Calendar.current.dateComponents([.year], from: date, to: self as Date)

    return Calendar.current.dateComponents([.year], from: date, to: self).year!

}
func monthsFrom(date:Date) -> Int{
    //        return NSCalendar.currentCalendar.components(.Month, fromDate: date, toDate: self, options: []).month
    return Calendar.current.dateComponents([.month], from: date as Date, to: self).month!
}
func weeksFrom(date:Date) -> Int{
    //return NSCalendar.currentCalendar.components(.WeekOfYear, fromDate: date, toDate: self, options: []).weekOfYear
    return Calendar.current.dateComponents([.weekOfYear], from: date, to: self).weekOfYear!
}
func daysFrom(date:Date) -> Int{
    //        return NSCalendar.currentCalendar.components(.Day, fromDate: date, toDate: self, options: []).day
    return Calendar.current.dateComponents([.day], from: date, to: self).day!
}
func hoursFrom(date:Date) -> Int{
    //        return NSCalendar.currentCalendar.components(.Hour, fromDate: date, toDate: self, options: []).hour
    return Calendar.current.dateComponents([.hour], from: date, to: self).hour!
}
func minutesFrom(date:Date) -> Int{
    //        return NSCalendar.currentCalendar.components(.Minute, fromDate: date, toDate: self, options: []).minute
    return Calendar.current.dateComponents([.minute], from: date, to: self).minute!
}
func secondsFrom(date:Date) -> Int{
    //        return NSCalendar.currentCalendar.components(.Second, fromDate: date, toDate: self, options: []).second
    return Calendar.current.dateComponents([.second], from: date, to: self).second!
}
func offsetFrom(date:Date) -> String
{
    if yearsFrom(date: date) > 0 {
        return "\(yearsFrom(date: date))y"
    }
    if monthsFrom(date: date) > 0 {
        return "\(monthsFrom(date: date))M"
    }
    if weeksFrom(date: date) > 0{
        return "\(weeksFrom(date: date))w"
    }
    if daysFrom(date: date) > 0 {
        return "\(daysFrom(date: date))d"
    }
    if hoursFrom(date: date) > 0 {
        return "\(hoursFrom(date: date))h"
    }
    if minutesFrom(date: date) > 0 {
        return "\(minutesFrom(date: date))m"
    }
    if secondsFrom(date: date) > 0 {
        return "\(secondsFrom(date: date))s"
    }
    return ""

}

}
2
Sazid Iqabal

truongkyのコード:のSwift 4バージョン

そして、現在ではなくTimeEndのオプションを追加します。

extension Date {

    func getElapsedInterval(to end: Date = Date()) -> String {

        if let interval = Calendar.current.dateComponents([Calendar.Component.year], from: self, to: end).day {
            if interval > 0 {
                return "\(interval) year\(interval == 1 ? "":"s")"
            }
        }

        if let interval = Calendar.current.dateComponents([Calendar.Component.month], from: self, to: end).month {
            if interval > 0 {
                return "\(interval) month\(interval == 1 ? "":"s")"
            }
        }

        if let interval = Calendar.current.dateComponents([Calendar.Component.weekOfMonth], from: self, to: end).weekOfMonth {
            if interval > 0 {
                return "\(interval) week\(interval == 1 ? "":"s")"
            }
        }

        if let interval = Calendar.current.dateComponents([Calendar.Component.day], from: self, to: end).day {
            if interval > 0 {
                return "\(interval) day\(interval == 1 ? "":"s")"
            }
        }

        if let interval = Calendar.current.dateComponents([Calendar.Component.hour], from: self, to: end).hour {
            if interval > 0 {
                return "\(interval) hour\(interval == 1 ? "":"s")"
            }
        }

        if let interval = Calendar.current.dateComponents([Calendar.Component.minute], from: self, to: end).minute {
            if interval > 0 {
                return "\(interval) minute\(interval == 1 ? "":"s")"
            }
        }

        return "Just now."
    }

}
1

これはコピーして貼り付けることができるソリューションです

 func timeAgoSinceDate(_ date:Date, numericDates:Bool = false) -> String? {
    let calendar = NSCalendar.current
    let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfYear, .month, .year, .second]
    let now = Date()
    let earliest = now < date ? now : date
    let latest = (earliest == now) ? date : now
    let components = calendar.dateComponents(unitFlags, from: earliest,  to: latest)

    if (components.year! >= 2) {
        return "\(components.year!)yr"
    } else if (components.year! >= 1){
        if (numericDates){
            return "1yr"
        } else {
            return "Last year"
        }
    } else if (components.month! >= 2) {
        return "\(components.month!)mo"
    } else if (components.month! >= 1){
        if (numericDates){
            return "1 mo"
        } else {
            return "Last mo"
        }
    } else if (components.weekOfYear! >= 2) {
        return "\(components.weekOfYear!) weeks"
    } else if (components.weekOfYear! >= 1){
        if (numericDates){
            return "1 week"
        } else {
            return "Last week"
        }
    } else if (components.day! >= 2) {
        return "\(components.day!) d"
    } else if (components.day! >= 1){
        if (numericDates){
            return "1 d"
        } else {
            return "1 d"
        }
    } else if (components.hour! >= 2) {
        return "\(components.hour!) hrs"
    } else if (components.hour! >= 1){
        if (numericDates){
            return "1 hr"
        } else {
            return "1 hr"
        }
    } else if (components.minute! >= 2) {
        return "\(components.minute!) m"
    } else if (components.minute! >= 1){
        if (numericDates){
            return "1 m"
        } else {
            return "2 m"
        }
    } else if (components.second! >= 3) {
        return "\(components.second!)s"
    } else {
        return "now"
    }

}

呼び出すには、単に使用します

    // the date you are getting information about 
let dateToReference = Date()
            if let timeAgo = timeAgoSinceDate(dateToReference) {
                //will be a String value
                print(timeAgo)

            } else {
                //just in case something goes wrong
                print("recently")

            }
1
Felecia Genet