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

时间:2017-09-23 06:38:42

标签: ios swift date firebase timestamp

我试图制作一个考勤应用程序,我对iOS和Firebase中的日期和时间感到困惑。

我使用date作为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日。

使用什么代码是正确的,以便我可以获得正确的日期时间戳和时间戳?

8 个答案:

答案 0 :(得分:52)

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

let timestamp = NSDate().timeIntervalSince1970

和For Decoding Unix Epoch time to Date()。

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

答案 1 :(得分:11)

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

另一件值得一提的是,如果你想用Swift操纵日期,你最好使用Date代替NSDate,除非你与某些人交往您应用中的Obj-C代码。

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

  

日期桥接到NSDate类。您可以互换使用这些   与Objective-C API交互的代码。

现在回答你的问题,我认为这里的问题是因为时区。

例如,如果你print(Date()),就像现在一样,你会得到:

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

这是格林威治标准时间(GMT)。

因此,根据您所在的位置(或用户所在的位置),您需要在存储Date之前(或之后,当您尝试访问数据时)调整时区:{/ 1}}

    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。)

答案 2 :(得分:11)

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

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

然后,您可以像在其他编程语言中一样使用它:

let timestamp = Date().currentTimeMillis()

答案 3 :(得分:2)

创建当前时间戳的简单方法。像下面一样,

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

答案 4 :(得分:2)

Swift 5

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

像这样打电话:

let timeStamp = Date.currentTimeStamp
print(timeStamp)

感谢@lenooh

答案 5 :(得分:1)

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

let currentDate = NSDate.now

答案 6 :(得分:0)

当您在Swift中将UTC时间戳(即2017-11-06 20:15:33 -08:00)转换为Date()对象时,Swift将时区归零为格林尼治标准时间(即加号或减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个左右的时区。现在,如果您想将字符串文字格式化为更用户友好的格式,则可以将上面的两个方法组合成类似这样的格式:

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是基本上任何值得其认可的框架都可以识别的配置文件。

答案 7 :(得分:0)

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

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)
    }