web-dev-qa-db-ja.com

iOS Swift-現在の現地時間と日付のタイムスタンプを取得

出席アプリを作成しようとしていますが、iOSとFirebaseの日付と時刻について本当に混乱しています。

日付をキーとして使用します。これはFirebaseデータベースの構造です。

--Employees
  --Unique_ID
     --Details
          Name: John
     --Attendance
          --dateToday
              Timein: 8:00 AM
              Timeout: 5:00 PM
              BreakStart: 12:00 PM
              BreakFinish: 1:00 PM

これは、キーとして使用した日付のタイムスタンプを取得するための私のコードです

 override func viewDidLoad() {
     super.viewDidLoad()

     let now = NSDate()
     let nowTimeStamp = self.getCurrentTimeStampWOMiliseconds(dateToConvert: now)

     // I save this dateToday as Key in Firebase
     dateToday = nowTimeStamp
}


func getCurrentTimeStampWOMiliseconds(dateToConvert: NSDate) -> String {
    let objDateformat: DateFormatter = DateFormatter()
    objDateformat.dateFormat = "yyyy-MM-dd"
    let strTime: String = objDateformat.string(from: dateToConvert as Date)
    let objUTCDate: NSDate = objDateformat.date(from: strTime)! as NSDate
    let milliseconds: Int64 = Int64(objUTCDate.timeIntervalSince1970)
    let strTimeStamp: String = "\(milliseconds)"
    return strTimeStamp
}

しかし、日付を元に戻すと、2017-09-22 16:00:00 +0000になります。これは私の場所では9月23日なので間違っています。

正しい日付のタイムスタンプと時刻のタイムスタンプを取得するために使用する適切なコードは何ですか?

28
TSM

現在の時間をfirebaseデータベースに保存するには、Unic Epoch Conversationを使用します。

let timestamp = NSDate().timeIntervalSince1970

そして、Unixエポック時間をDate()にデコードするため。

let myTimeInterval = TimeInterval(timestamp)
let time = NSDate(timeIntervalSince1970: TimeInterval(myTimeInterval))
58
Satish Babariya

UNIXタイムスタンプだけが必要な場合は、拡張機能を作成します。

extension Date {
    func currentTimeMillis() -> Int64 {
        return Int64(self.timeIntervalSince1970 * 1000)
    }
}

その後、他のプログラミング言語と同じように使用できます。

let timestamp = Date().currentTimeMillis()
15
lenooh

最初に、タイムスタンプをNSNumberとして保存するのではなく、FirebaseデータベースにStringとして保存することをお勧めします。

ここで言及する価値のあるもう1つのことは、Swiftで日付を操作する場合は、アプリでObj-Cコードを操作する場合を除いて、Dateの代わりにNSDateを使用することをお勧めします。

もちろん両方を使用できますが、ドキュメントには次のように記載されています。

NSDateクラスへの日付ブリッジ。これらは、Objective-C APIとやり取りするコードで交換可能に使用できます。

さて、あなたの質問に答えるために、ここでの問題はタイムゾーンのためだと思います。

たとえば、print(Date())の場合、今のところ、次のようになります。

2017-09-23 06:59:34 +0000

これはグリニッジ標準時(GMT)です。

したがって、あなたがいる場所(またはユーザーがいる場所)に応じて、Dateを保存する前(またはデータにアクセスしようとするときなど)にタイムゾーンを調整する必要があります。

    let now = Date()

    let formatter = DateFormatter()

    formatter.timeZone = TimeZone.current

    formatter.dateFormat = "yyyy-MM-dd HH:mm"

    let dateString = formatter.string(from: now)

次に、適切にフォーマットされたStringがあり、あなたの場所の現在の時刻を反映し、あなたはそれを使って自由に何でもできます:)(それをDate/NSNumberに変換するか、データベースにStringとして直接保存します) )

12
Alex

現在のタイムスタンプを作成する簡単な方法。以下のように、

func generateCurrentTimeStamp () -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy_MM_dd_hh_mm_ss"
    return (formatter.string(from: Date()) as NSString) as String
}
2
User558

UTCタイムスタンプ(2017-11-06 20:15:33 -08:00)をSwiftのDate()オブジェクトに変換すると、SwiftはタイムゾーンをGMT(プラスまたはマイナス)にゼロにします0)。時間間隔を計算する場合、これは問題になりません。ただし、何時間(および分、時間で分割されていないが:45または:30にある多くの時間帯があるため)はゼロ化から加算または減算されるためです。タイムゾーンは日付の時間(場合によっては分)の値に加算または減算されるため、絶対的な時点は変更されません。ただし、DateFormatter()またはISO8601DateFormatter()を使用してその日付オブジェクトを文字列に変換する場合、元のタイムゾーンがゼロにリセットされるため、問題が発生します。

現在、RFC3339(2017-11-06T20:15:33-08:00)を使用することを好みます。これは、ISO8601標準時間形式のインターネットフレンドリーな形式です。おそらく、あなたがいつか接続するサードパーティのAPIを使用する可能性があるので、今すぐ使用するべきだと思います。 Swiftの形式はyyyy-MM-dd'T'HH:mm:ssXXXXXです。 Swiftには、文字列リテラルを非常に簡単に日付オブジェクトに変換できるISO8601DateFormatter()もあります。

func getDateFromUTC(RFC3339: String) -> Date? {
    let formatter = ISO8601DateFormatter()
    return formatter.date(from: RFC3339)
}

また、RFC3339形式を使用すると、タイムゾーンの抽出も非常に簡単になります。

func getTimeZoneFromUTC(RFC3339: String) -> TimeZone? {
    switch RFC3339.suffix(6) {
    case "+05:45":
        return TimeZone(identifier: "Asia/Kathmandu")
    default:
        return nil
    }
}

もちろん、他の37かそこらのタイムゾーンに最適な方法を使用して入力する必要があります。そして今、その文字列リテラルをよりユーザーフレンドリーなものにフォーマットしたい場合、上記の2つの方法をこのようなものに組み合わせることができます:

func getFormattedDateFromUTC(RFC3339: String) -> String? {
    guard let date = getDateFromUTC(RFC3339: RFC3339),
        let timeZone = getTimeZoneFromUTC(RFC3339: RFC3339) else {
            return nil
    }
    let formatter = DateFormatter()
    formatter.dateFormat = "h:mma EEE, MMM d yyyy"
    formatter.amSymbol = "AM"
    formatter.pmSymbol = "PM"
    formatter.timeZone = timeZone // preserve local time zone
    return formatter.string(from: date)
}

したがって、この文字列"2018-11-06T17:00:00+05:45"は、カトマンズのどこか5:00 PMを表し、5:00PM Tue, Nov 6 2018を出力し、マシンの場所に関係なく現地時間を表示します。もちろん、コンテキストのローカル時間を使用してフォーマットしたくない場合は、timeZoneプロパティを設定しないでください。

このスレッドのいくつかの提案に対する補足として、日付をFirebaseに文字列として保存することをお勧めします。特にRFC3339のような形式を使用して、日付を文字列として保存すると、このデータプラットフォームは不可知になります。任意のフレームワークの任意のプラットフォーム上の任意のデータベースに切り替えることができ、文字列は常に単なる文字列であるため、ロジックを変更する必要はありません。そして、RFC3339は、基本的にその価値のあるフレームワークが認識する1つのプロファイルです。

0
bsod