【问题标题】:iOS Swift - Get the Current Local Time and Date TimestampiOS Swift - 获取当前本地时间和日期时间戳
【发布时间】: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 是要创建的重对象,因此如果您经常调用该函数,请将其导出到函数范围之外

标签: ios swift date firebase timestamp


【解决方案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),我会再次获得格林威治标准时间。
            猜你喜欢
            • 2013-03-10
            • 2010-12-31
            • 1970-01-01
            • 1970-01-01
            • 2021-09-26
            • 2020-01-02
            • 2012-12-04
            • 2016-02-07
            相关资源
            最近更新 更多