iOS Swift - 获取当前本地时间和日期时间戳

Posted

技术标签:

【中文标题】iOS Swift - 获取当前本地时间和日期时间戳【英文标题】:iOS Swift - Get the Current Local Time and Date Timestamp 【发布时间】:2018-03-04 17:56:45 【问题描述】:

我正在尝试制作一个考勤应用程序,但我对 ios 和 Firebase 中的日期和时间感到非常困惑。

我使用日期作为 Key,这是我的 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 日。

使用什么代码才能获得正确的日期时间戳和时间时间戳?

【问题讨论】:

你的时区是UTC+0800是正确的。 print 始终以 UTC 显示 Dates。而2017-09-22 16:00:00 +00002017-09-23 00:00:00 +0800 是完全相同的时间点。顺便说一句:不要在 Swift 3 中使用 NSDate DateFormatter 是要创建的重对象,因此如果您经常调用该函数,请将其导出到函数范围之外 【参考方案1】:

关于扩展@MacacoAzul 的答案是我目前的工作示例:

import SwiftUI

struct TimestampDemo: View 
    var body: some View 
        
        Text(getActualTimeStamp(1))
            .padding(10)
       
        Text(getActualTimeStamp(2))
            .padding(10)
        
        Text(getActualTimeStamp(3))
            .padding(10)
        
        Text(getActualTimeStamp(4))
            .padding(10)
    
    
    
    func getActualTimeStamp(_ tipo:Int) -> String 
            let date = Date()
            let formatter = DateFormatter()
            if tipo == 1
                formatter.dateFormat = "dd/MM/yyyy"
             else if tipo == 2
                formatter.dateFormat = "yyyy-MM-dd HH:mm"
            else if tipo == 3
                formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            
            else if tipo == 4  
                formatter.dateFormat = "dd-MM-yyyy"
            

            return formatter.string(from: date)
        


struct TimestampDemo_Previews: PreviewProvider 
    static var previews: some View 
        TimestampDemo()
    

Swift 语言版本: 5

【讨论】:

【参考方案2】:

您甚至可以根据需要创建一个函数来返回不同的时间戳:

func dataatual(_ tipo:Int) -> String 
        let date = Date()
        let formatter = DateFormatter()
        if tipo == 1
            formatter.dateFormat = "dd/MM/yyyy"
         else if tipo == 2
            formatter.dateFormat = "yyyy-MM-dd HH:mm"
         else 
            formatter.dateFormat = "dd-MM-yyyy"
        

        return formatter.string(from: date)
     

【讨论】:

【参考方案3】:

当我们将 UTC 时间戳 (2017-11-06 20:15:33 -08:00) 转换为 Date 对象时,时区将归零为 GMT。对于计算时间间隔,这不是问题,但它可以用于在 UI 中呈现时间。

我喜欢 RFC3339 格式 (2017-11-06T20:15:33-08:00) 的通用性。 Swift 中的日期格式是 yyyy-MM-dd'T'HH:mm:ssXXXXX,但 RFC3339 允许我们利用 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:30":
        return TimeZone(identifier: "Asia/Kolkata")

    case "+05:45":
        return TimeZone(identifier: "Asia/Kathmandu")

    default:
        return nil

    


我们需要考虑大约 37 个其他时区,您可以决定哪些时区,因为没有明确的列表。有些标准计算的时区更少,有些标准更多。大多数时区在整点休息,有些在半小时,有些在0:45,有些在0:15

我们可以将上面的两种方法组合成这样:

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,将打印5:00PM Tue, Nov 6 2018,显示当地时间,无论机器在哪里。

顺便说一句,我建议将日期存储为远程字符串(包括具有本机日期对象的 Firestore),因为我认为远程数据应该不可知,以尽可能减少服务器和客户端之间的摩擦。

【讨论】:

【参考方案4】:

如果您为 iOS 13.0 或更高版本编写代码并需要时间戳,则可以使用:

let currentDate = NSDate.now

【讨论】:

这不是 10 位时间戳【参考方案5】:

Swift 5

extension Date 
    static var currentTimeStamp: Int64
        return Int64(Date().timeIntervalSince1970 * 1000)
    

这样调用:

let timeStamp = Date.currentTimeStamp
print(timeStamp)

谢谢@lenooh

【讨论】:

【参考方案6】:

如果您只想要 unix 时间戳,请创建一个扩展:

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

然后你就可以像在其他编程语言中一样使用它了:

let timestamp = Date().currentTimeMillis()

【讨论】:

迄今为止最好的答案。【参考方案7】:

创建当前时间戳的简单方法。如下图,

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

【讨论】:

【参考方案8】:

为了将当前时间保存到 firebase 数据库,我使用 Unic Epoch Conversation:

let timestamp = NSDate().timeIntervalSince1970

用于将 Unix 纪元时间解码为 Date()。

let myTimeInterval = TimeInterval(timestamp)
let time = NSDate(timeIntervalSince1970: TimeInterval(myTimeInterval))

【讨论】:

NSDate().timeIntervalSince1970 是否会计算时区,或者有什么方法可以针对不同的时区进行计算? 纪元时间,根据定义,是 UTC。它是 UTC 时区自 1970 年 1 月 1 日午夜以来经过的秒数/毫秒数。时区信息仅用于以特定的人类语言显示,而不用于存储或计算任何内容。【参考方案9】:

首先,我建议您将时间戳作为 NSNumber 存储在 Firebase 数据库中,而不是将其存储为 String

这里值得一提的是,如果您想使用 Swift 操作日期,最好使用 Date 而不是 NSDate,除非您在应用程序中与一些 Obj-C 代码进行交互。

您当然可以同时使用两者,但文档说明:

日期桥接到 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..)

【讨论】:

dateString 最终是正确的。但是,如果我在末尾添加formatter.date(from: dateString),我会再次获得格林威治标准时间。

以上是关于iOS Swift - 获取当前本地时间和日期时间戳的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Kotlin 中获取当前的本地日期和时间

Swift - iOS UTC 日期和时间设置为带有偏移的设备日期和时间格式

在 Swift 3 中获取当前日期? [关闭]

从服务器获取当前日期时间并将其转换为 c# 中的本地时间

Swift 5 中从日期时间字符串到当前时间的天数时差

iOS学习笔记37-时间和日期计算