2017-08-20 2 views
4

私のサーバコールでは、1データあたりの日付時間をJSONデータで取得しています。今度はそれまでの経過時間を計算し、それをデータ構造にロードします。私が今やっているやり方は、今、長い道のりを踏み出しています。使用すべき別のデザインプラクティスはありますか?フォロー機能は、私が今スイフト - 経過時間の計算に時間がかかりますか?

func dateDiff(_ dateStr:String) -> String { 
    var timeAgo = "10m" 

    let formatter = DateFormatter() 
    formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss" 
    formatter.timeZone = NSTimeZone(name: "AST") as! TimeZone 


    let dateFormatter = DateFormatter() 
    dateFormatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss" 
    dateFormatter.timeZone = NSTimeZone(name: "AST") as! TimeZone 

    let now = formatter.string(from: Date()) 

    if let date = formatter.date(from: dateStr){ 
     if let nowDate = formatter.date(from: now){ 
     let components = Calendar.current.dateComponents([.day,.hour,.minute,.second], from: date, to: nowDate) 
     let sec = components.second 
     let min = components.minute 
     let hours = components.hour 
     let days = components.day 
     if (sec! > 0){ 
      if let secc = sec { 
       timeAgo = "\(secc)s" 
      } 
     } 
     if (min! > 0){ 
      if let minn = min { 
       timeAgo = "\(minn)m" 
      }   } 
     if(hours! > 0){ 
      if let hourss = hours { 
       timeAgo = "\(hourss)h" 
      } 
     } 
     if(days! > 0){ 
      if let dayss = days { 
       timeAgo = "\(dayss)d" 
      } 
     } 
    } 
    } 
    return timeAgo 
} 
+0

'formatter'と' dateFormatter'の違いはどこですか?後者は使用されていないようです。'Date()'を文字列に変換して 'Date'に戻すのはなぜですか? –

+0

['DateComponentsFormatter'](https://developer.apple.com/documentation/foundation/datecomponentsformatter)を見てください。 –

答えて

0

パフォーマンス上の理由から、日付フォーマッタのインスタンス化をメソッドから取り除く必要があります。これは、それが悪名高い計算集約型であるためです。

また、DateComponentsFormatterを使用して経過時間の書式を簡略化することをお勧めします。

let dateFormatter: DateFormatter = { 
    let _formatter = DateFormatter() 
    _formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss" 
    _formatter.locale = Locale(identifier: "en_US_POSIX") 
    _formatter.timeZone = TimeZone(abbreviation: "AST") // Curious; we usually use `TimeZone(secondsFromGMT: 0)` (i.e. GMT/UTC/Zulu) 
    return _formatter 
}() 

let componentsFormatter: DateComponentsFormatter = { 
    let _formatter = DateComponentsFormatter() 
    _formatter.maximumUnitCount = 1 
    _formatter.unitsStyle = .abbreviated 
    return _formatter 
}() 

をしてから機能が大幅に簡略化されています:

だから、あなたの2つのフォーマッタを定義

func dateDiff(_ string: String) -> String? { 
    guard let date = dateFormatter.date(from: string) else { return nil } 

    return componentsFormatter.string(from: date, to: Date()) 
} 

また、次の点に注意してください、私はTimeZone直接、むしろラウンドを使用

  • - NSTimeZoneを介してトリッピング;
  • localeen_US_POSIXに設定します。日付文字列のソースがWebサービスまたはデータベースの場合は、always useにする必要があります。
  • 「今」の文字列への変換を取り除きました。ちょうどDate()を直接使用してください。

もう1つ疑わしいのは、ASTをタイムゾーンに使用することだけです。通常、日付文字列はGMT/UTC/Zulu(たとえば、RFC 3339またはISO 8601)に保存されます。これを制御できる場合は、ユーザーがタイムゾーンを変更した場合の問題を回避して、おそらくベストプラクティスです。

0

を使用していますそれは、作成することがやや高価だし、その後たDateFormatterはdateDiffが呼び出されるたびにどのオブジェクトです。 dateDiffを所有するオブジェクトがアプリの起動またはJSONのロードごとに1回作成される場合、最適化するために行うことの1つは、日付フォーマッターをクラスのメンバーにすることです。したがって、dateDiffを呼び出すたびに再作成しないでください。あなたのクラスの先頭に

var formatter : DateFormatter 
var dateFormatter : DateFormatter 

をしてからinit機能でそれを初期化します。

言い換えれば、置きます。

0

あなたのコードで始まるには余りにも冗長だった、あなたはそれを有意に短縮している可能性:

if let day = components.day, day > 0 { 
    timeAgo = "\(day)d" 
} else if let hour = components.hour, hour > 0 { 
    timeAgo = "\(hour)h" 
} else if let minute = components.minute, minute > 0 { 
    timeAgo = "\(minute)m" 
} else if let second = components.second, second > 0 { 
    timeAgo = "\(second)s" 
} 

をしかし、それを行うには良い方法は、iOS 8とOS X 10.10以降で使用可能DateComponentsFormatterを、使用することです:ここでは

let componentsFormatter = DateComponentsFormatter() 
componentsFormatter.allowedUnits = [.second, .minute, .hour, .day] 
componentsFormatter.maximumUnitCount = 1 
componentsFormatter.unitsStyle = .abbreviated 

let timeAgo = componentsFormatter.string(from: dateComponents)! 

は、それはあなたのために何をするかのいくつかの例です:

let dateComponents1 = DateComponents(calendar: .current, day: 1, hour: 4, minute: 6, second: 3) 
let dateComponents2 = DateComponents(calendar: .current, day: 0, hour: 4, minute: 6, second: 3) 
let dateComponents3 = DateComponents(calendar: .current, day: 0, hour: 0, minute: 6, second: 3) 
let dateComponents4 = DateComponents(calendar: .current, day: 0, hour: 0, minute: 0, second: 3) 

print(componentsFormatter.string(from: dateComponents1)!) // 1d 
print(componentsFormatter.string(from: dateComponents2)!) // 4h 
print(componentsFormatter.string(from: dateComponents3)!) // 6m 
print(componentsFormatter.string(from: dateComponents4)!) // 3s