时间处理随记

229 阅读4分钟

NSDate

iOS中的NSDate对象存放的日期始终是UTC的标准时间

  • NSDateComponents封装了具体年月日、时秒分、周、季度等可以快速而简单地获取某个时间点对应的“年”,“月”,“日”,“时”,“分”,“秒”,“周”等信息 ,因此能返回具体的day、week、month数据(数据都是从1开始)。NSDateComponents不仅可以表示一个时间点,还可以表示时间段 如:两周,三个月,20年,7天

    let date = Date()
    let calendar = NSCalendar.current
    print("纪元era = (calendar.component(.era, from: date))")
    print("年year = (calendar.component(.year, from: date))")
    print("月month = (calendar.component(.month, from: date))")
    print("日day = (calendar.component(.day, from: date))")
    print("时hour = (calendar.component(.hour, from: date))")
    print("分minute = (calendar.component(.minute, from: date))")
    print("秒second = (calendar.component(.second, from: date))")
    print("周(calendar.component(.weekday, from: date))")
    print("本月第(calendar.component(.weekOfMonth, from: date))周")
    print("今年第(calendar.component(.weekOfYear, from: date))周")
    ​
    纪元era = 1
    年year = 2023
    月month = 3
    日day = 31
    时hour = 14
    分minute = 3
    秒second = 196
    本月第4周
    今年第13
  • NSCalendar默认为公历(阳历)

  • NSDateFormatter表示的时间默认以阳历为参考

  • DateFormatter:常用于把NSDate时间转换成需要的String时间格式

    "yyyy-MM-dd HH:mm:ss eee"; 
    d : 将日显示为不带前导零的数字(如 1
    dd : 将日显示为带前导零的数字(如 01)。
    EEE : 将日显示为缩写形式(例如 Sun)。
    EEEE : 将日显示为全名(例如 Sunday)
    
  • NSTimeZone:时区信息

时间戳(timestamp)

通常是一个字符序列,唯一地标识某一刻的时间,数值是从1970年1月1日8点到现在时间的总秒数(毫秒数)

UTC

世界统一时间(世界标准时间)

中国大陆的时间与UTC的时差是+8小时,即UTC+8

GMT

是指位于伦敦郊区的皇家格林尼治天文台的标准时间(开发中不常用)

通过 [NSDate Date] 获取到的时间就是GMT地区的时间

基础功能及转换

let date = Date()
print("date = (date)")
​
date = 2023-03-24 07:02:23 +0000 // UTC时间 +8 小时正好是当前北京时间

获取北京时间(当前时间)

let date = Date()
let dateFormat = DateFormatter()
dateFormat.dateFormat="yyyy-MM-dd HH:mm:ss eeee"
let currentTime : String = dateFormat.string(from: date) // Date格式转String格式
print("date = (currentTime)")
currentTime = 2023-03-27 10:17:51 Monday // String类型的当前时间
​
let currentDate : Date = dateFormat.date(from: currentTime)! // String格式转Date格式
print("currentDate = (currentDate)") 
​
currentDate = 2023-03-27 02:17:51 +0000 // Date类型的当前时间 因为没有设置相应的时区 所以缺少八小时

String格式转Date格式需要注意的是平时服务器给的时间一般都是本地时间(北京时间),而Date存储的是是UTC时间,直接转换会发现少了八小时

// 添加时区信息在输出 此时的date就跟当前对上了
dateFormat.timeZone = TimeZone(abbreviation: "UTC") 
currentDate = 2023-03-27 10:20:39 +0000 

时间戳转换

// date转时间戳
let date = Date()
let timeTDateTI: TimeInterval = date.timeIntervalSince1970
print("timeTDateTI = (Int(timeTDateTI))")
​
timeTDateTI = 1679646639 // 毫秒就x1000
​
//字符串转时间戳 需要把string转场date 在通过date转时间戳即可

特殊例子

let timeT = "2020-12-17T06:48:49.919Z" //成为 ISO8601 格式 日期和时间之后用T来分割 Z表示UTC时间 想要转换成当地时间要+8小时
let dateFormat = DateFormatter()
dateFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // 使用该格式对解析ISO8601格式时间
dateFormat.timeZone = NSTimeZone.local // 返回本地时区
let timeTDate : Date = dateFormat.date(from: timeT)!
print("timeTDate = (timeTDate)")
​
timeTDate = 2020-12-17 06:48:49 +0000  //获取到date转换成其他格式就很方便了
​
dateFormat.dateFormat = "yyyy-MM-dd HH:mm:ss"
let timeTStr = dateFormat.string(from: timeTDate)
print("timeTStr = (timeTStr)")
​
timeTStr = 2020-12-17 14:48:49
// 有意思的是采用格式"yyyy-MM-dd'T'HH:mm:ss.SSSZ" 默认的Date都是UTC时间 但转成String却是当前时区时间 
// 并不需要添加 dateFormat.timeZone = TimeZone(abbreviation: "UTC") 等转时区方法

项目实用

  • 比较

    let nowDate = NSDate()
    let beforeTime = "2019-3-27"let dateFormat = DateFormatter()
    dateFormat.dateFormat = "yyyy-MM-dd HH:mm"
    let currentTime : String = dateFormat.string(from: nowDate as Date)
    ​
    dateFormat.timeZone = TimeZone(abbreviation: "UTC")
    let currentDate : NSDate = dateFormat.date(from: currentTime)! as NSDatelet beforeDate : Date = dateFormat.date(from: beforeTime)!
    let bl:Bool = currentDate.isEqual(to: beforeDate)  // isEqual 比较方法只支持 NSDate 而非 Date// 比较两个时间是否相同
    currentDate = 2023-03-27 11:02:00 +0000
    beforeDate = 2019-03-27 11:56:00 +0000
    bl = false// 比较两个时间大小
    let result : ComparisonResult = currentDate.compare(beforeDate)
    print("result = (result)")
    result = NSComparisonResult(rawValue: 1)
    ​
    @frozen public enum ComparisonResult : Int, @unchecked Sendable {
      case orderedAscending = -1 // 左操作数小于右操作数
      case orderedSame = 0  // 两个操作数相等
      case orderedDescending = 1 // 左操作数大于右操作数
    }
    ​
    // 比较两个时间,返回 较早/较晚的时间
    let eardate = currentDate.earlierDate(beforeDate) // 较早
    let latdate = currentDate.laterDate(beforeDate) // 较晚
    
  • 时间间隔的计算

    let compt : NSDateComponents = NSCalendar.current.dateComponents([.year, .month, .hour, .minute, .second], from: beforeDate, to: currentDate as Date) as NSDateComponents
    ​
    compt = <NSDateComponents: 0x600003e903d0> {
        Calendar Year: 3
        Month: 11
        Hour: 671
        Minute: 53
        Second: 0
    }