美文网首页
iOS - 聊聊时间(Date)

iOS - 聊聊时间(Date)

作者: Longshihua | 来源:发表于2019-03-27 17:28 被阅读0次

    时间概念

    • GMT

    格林尼治标准时间(旧译格林威治平均时间或格林威治标准时间;英语:GreenwichMeanTime,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。 理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治时)的时间。由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能和实际的太阳时相差16分钟。

    • UTC

    协调世界时,又称世界统一时间、世界标准时间、国际协调时间。由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。

    协调世界时是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。中国大陆采用ISO 8601-1988的《数据元和交换格式信息交换日期和时间表示法》(GB/T 7408-1994)称之为国际协调时间,代替原来的GB/T 7408-1994;中国台湾采用CNS 7648的《资料元及交换格式–资讯交换–日期及时间的表示法》,称之为世界统一时间。

    Date介绍

    A specific point in time, independent of any calendar or time zone.

    SwiftDate是一个结构体(struct),该结构体提供了日期相关的操作

    public struct Date : ReferenceConvertible, Comparable, Equatable {}
    

    创建Date

    public init()
    public init(timeIntervalSinceNow: TimeInterval)
    public init(timeIntervalSince1970: TimeInterval)
    public init(timeInterval: TimeInterval, since date: Date)
    public init(timeIntervalSinceReferenceDate ti: TimeInterval)
    
    • init()

    该方法会根据当前的日期和时间来创建Date

    let date = Date()
    print("now: \(date)")
    // now: 2019-03-27 06:37:23 +0000
    
    • init(timeIntervalSinceNow: TimeInterval)

    该方法会根据当前时间为基准,然后过了指定的时间(秒)创建Date,如下面5秒之后

    let date1 = Date()
    print("date1: \(date1)")
    
    let date2 = Date(timeIntervalSinceNow: 5)
    print("date2: \(date2)")
    
    // date1: 2019-03-27 06:45:29 +0000
    // date2: 2019-03-27 06:45:34 +0000
    
    • init(timeIntervalSince1970: TimeInterval)

    该方法以世界时间(UTC)1970年1月1日凌晨为参考创建Date,参数是相对于指定时间的间隔

    let date = Date(timeIntervalSince1970: 0)
    print("date: \(date)")
    // 1970-01-01 00:00:00 +0000
    
    • init(timeInterval: TimeInterval, since date: Date)

    方法根据给定的date和指定的时间间隔创建一个新的Date

    let currentDate = Date()
    print("currentDate: \(currentDate)")
    let date = Date(timeInterval: 2, since: currentDate)
    print("date: \(date)")
    
    currentDate: 2019-03-27 07:06:47 +0000
    date: 2019-03-27 07:06:49 +0000
    
    • init(timeIntervalSinceReferenceDate ti: TimeInterval)

    返回以2001/01/01 UTC为基准,然后过了secs秒的时间

    let date = Date(timeIntervalSinceReferenceDate: 2)
    print("date: \(date)")
    // date: 2001-01-01 00:00:02 +0000
    

    Date比较

    public func compare(_ other: Date) -> ComparisonResult 
    public static func == (lhs: Date, rhs: Date) -> Bool //返回true,表示两个Date值代表相同的时间
    public static func < (lhs: Date, rhs: Date) -> Bool // 左边的时间早返回true
    public static func > (lhs: Date, rhs: Date) -> Bool // 左边的时间晚返回true
    

    ComparisonResult是一个枚举,用于表示请求排序的结果,如下

    public enum ComparisonResult : Int {
        case orderedAscending // 操作数a < 操作数b 
        case orderedSame // a == b
        case orderedDescending // a > b
    }
    

    对于Date而言

    当前date值早于anotherDate时返回orderedAscending
    当前date值与anotherDate相同时返回orderedSame
    当前date值晚于anotherDate时返回orderedDescending

    let date1 = Date(timeIntervalSinceNow: 1)
    let date2 = Date(timeIntervalSinceNow: 5)
    let result = date1.compare(date2)
    switch result {
    case .orderedAscending:
        print("orderedAscending")
    case .orderedSame:
        print("orderedSame")
    case .orderedDescending:
        print("orderedDescending")
    }
    // orderedAscending
    

    获取时间间隔

    public func timeIntervalSince(_ date: Date) -> TimeInterval // 以date为基准时间,返回实例保存的时间与date的时间间隔
    public var timeIntervalSinceNow: TimeInterval { get } // 以当前时间(Now)为基准时间,返回实例保存的时间与当前时间(Now)的时间间隔
    public var timeIntervalSince1970: TimeInterval { get } //以1970/01/01 UTC为基准时间,返回实例保存的时间与1970/01/01 UTC的时间间隔
    public var timeIntervalSinceReferenceDate: TimeInterval { get } // 以2001/01/01 UTC为基准时间,返回实例保存的时间与2001/01/01 UTC的时间间隔
    public static var timeIntervalSinceReferenceDate: TimeInterval { get } // 以2001/01/01 UTC为基准时间,返回当前时间(Now)与2001/01/01 UTC的时间间隔
    public static let timeIntervalBetween1970AndReferenceDate: TimeInterval //1970/01/01 UTC与2001/01/01 UTC的时间间隔
    

    DateFormatter

    A formatter that converts between dates and their textual representations.

    DateFormatter简单理解就是Date的格式化工具,展示成易于理解的样式

    open class DateFormatter : Formatter { }
    

    对象之间的转换

    open func string(from date: Date) -> String //  Date ->  String
    open func date(from string: String) -> Date? // String -> Date
    

    格式化和样式

    open var dateFormat: String!
    open var dateStyle: DateFormatter.Style
    open var timeStyle: DateFormatter.Style
    

    DateFormatter.Style是一个枚举,如下

    extension DateFormatter {
        public enum Style : UInt {
            case none
            case short
            case medium
            case long
            case full
        }
    }
    

    简单使用

    let date = Date()
    let formatter = DateFormatter()
    formatter.dateStyle = .full
    formatter.timeStyle = .full
    
    let dateString = formatter.string(from: date)
    print(dateString)
    

    测试修改timeStyle的样式,运行如下

    // full full
    Wednesday, March 27, 2019 at 4:12:29 PM China Standard Time
    // full long
    Wednesday, March 27, 2019 at 4:13:19 PM GMT+8
    // full medium
    Wednesday, March 27, 2019 at 4:11:27 PM
    // full short
    Wednesday, March 27, 2019 at 4:13 PM
    // full none
    Wednesday, March 27, 2019
    

    自定义格式化

    实际的开发中,更多的是根据需求,自定义显示样式,将样式字符串赋值dateFormat属性

    let date = Date()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    
    let dateString = formatter.string(from: date)
    print(dateString) // 2019-03-27 16:19:10
    

    一些格式化形式

    • EEEE:表示星期几(Monday),使用1-3个字母表示周几的缩写
    • MMMM:月份的全写(October),使用1-3个字母表示月份的缩写
    • dd:表示日期,使用一个字母表示没有前导0
    • YYYY:四个数字的年份
    • HH:两个数字表示的小时
    • mm:两个数字的分钟
    • ss:两个数字的秒
    • zzz:三个字母表示的时区
    屏幕快照 2019-03-26 下午7.07.14.png

    基本使用

    • 时间(Date)转字符串(String)
    // 获取当前时间
    let now = Date()
    
    // 格式化
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy年MM月dd日 HH:mm:ss"
    print("当前日期时间:\(formatter.string(from: now))") //当前日期时间:2019年03月27日 17:06:22
    
     // 当前时间的时间戳
    let timeInterval:TimeInterval = now.timeIntervalSince1970
    let timeStamp = Int(timeInterval)
    print("时间戳:\(timeStamp)") // 时间戳:1553677582
    
    • 将时间戳转为日期时间
    // 时间戳
    let timeStamp = 1553677582
    
    // 转换为时间
    let timeInterval:TimeInterval = TimeInterval(timeStamp)
    let date = Date(timeIntervalSince1970: timeInterval)
    
    // 格式话输出
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy年MM月dd日 HH:mm:ss"
    print("时间:\(formatter.string(from: date))") // 时间:2019年03月27日 17:06:22
    
    • String转换为Date
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZ" // 格式
    let date = dateFormatter.date(from: strDate) // strDate:字符串日期
    
    • 拆分Date

    有时候你可能想获取Date中的day,month,hour 等的值。这里就需要使用DateComponents通常和 Calendar.

    Calendar 实现了真正的从DateDateComponents的转换以及从日期的组成元素到日期对象的转换.

    Date到DateComponents

    let currentdate = Date()
    let calendar = Calendar.current
    
    let dateComponents = calendar.dateComponents([.year,.month, .day, .hour,.minute,.second], from: currentdate)
    
    print("year: \(dateComponents.year), \n month: \(dateComponents.month),\n day: \(dateComponents.day),\n hour: \(dateComponents.hour),\n minute: \(dateComponents.hour),\n second: \(dateComponents.second)")
    
    // 运行结果
    year: Optional(2019), 
     month: Optional(3),
     day: Optional(27),
     hour: Optional(16),
     minute: Optional(16),
     second: Optional(17)
    

    DateComponents到Date

    let calendar = Calendar.current
    
    var dateComponents = DateComponents()
    dateComponents.day = 28
    dateComponents.month = 3
    dateComponents.year = 2019
    dateComponents.hour = 18
    dateComponents.minute = 35
    dateComponents.second = 16
    
    let date = calendar.date(from: dateComponents)
    print(date!) // 2019-03-28 10:35:16 +0000
    

    Date简单的扩展

    实际开发过程中将相关功能添加到extension中是一种很好的方式

    extension Date {
        public init?(fromString string: String, format: String) {
            let formatter = DateFormatter()
            formatter.dateFormat = format
            if let date = formatter.date(from: string) {
                self = date
            } else {
                return nil
            }
        }
    
        public func toString(format: String) -> String {
            let formatter = DateFormatter()
            formatter.dateFormat = format
            return formatter.string(from: self)
        }
    
        public func timePassed() -> String {
            let date = Date()
            let calendar = Calendar.current
            let components = (calendar as NSCalendar).components([.year, .month, .day, .hour, .minute, .second], from: self, to: date, options: [])
    
            if components.year! >= 1 {
                return "\(components.year!)年前"
            } else if components.month! >= 1 {
                return "\(components.month!)个月前"
            } else if components.day! >= 1 {
                return "\(components.day!)天前"
            } else if components.hour! >= 1 {
                return "\(components.hour!)小时前"
            } else if components.minute! >= 1 {
                return "\(components.minute!)分钟前"
            } else if components.second == 0 {
                return "刚刚"
            } else {
                return "\(components.second!)秒前"
            }
        }
    
        public var year: Int {
            return Calendar.current.component(Calendar.Component.year, from: self)
        }
    
        public var month: Int {
            return Calendar.current.component(Calendar.Component.month, from: self)
        }
    
        public var weekday: String {
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "EEEE"
            return dateFormatter.string(from: self)
        }
    
        public var monthAsString: String {
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "MMMM"
            return dateFormatter.string(from: self)
        }
    
        public var day: Int {
            return Calendar.current.component(.day, from: self)
        }
    
        public var hour: Int {
            return Calendar.current.component(.hour, from: self)
        }
    
        public var minute: Int {
            return Calendar.current.component(.minute, from: self)
        }
    
        public var second: Int {
            return Calendar.current.component(.second, from: self)
        }
    }
    

    实际场景

    • 1、判断两个日期是否为同一天

    OC实现

    - (BOOL)isToday {
        NSCalendar *calendar = [NSCalendar currentCalendar];
        int unit = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear;
    
        NSDateComponents *nowCmps = [calendar components:unit fromDate:[NSDate date]];
        NSDateComponents *selfCmps = [calendar components:unit fromDate:self];
    
        return (selfCmps.year == nowCmps.year) && (selfCmps.month == nowCmps.month) && (selfCmps.day == nowCmps.day);
    }
    

    Swift实现

    1、格式化成字符串比较

    将两个日期格式化成只包含年月日的字符串,再比较两个字符串是否相等。

    func isTheSameDay(startDate: Date, endDate: Date) {
        // 初始化日期格式器
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMdd"
    
        // 开始比较
        if formatter.string(from: startDate) == formatter.string(from: endDate) {
            print("它们是同一天")
        } else {
            print("它们不是同一天")
        }
    }
    

    2、取出日期的年、月、日分别进行比较

    func isTheSameDay(startDate: Date, endDate: Date) {
        let calendar = Calendar.current
        let comp1 = calendar.dateComponents([.year,.month,.day], from: startDate)
        let comp2 = calendar.dateComponents([.year,.month,.day], from: endDate)
    
        //开始比较
        if comp1.year == comp2.year &&
            comp1.month == comp2.month &&
            comp1.day == comp2.day {
            print("它们是同一天")
        } else {
            print("它们不是同一天")
        }
    }
    

    3、使用Calendar的isDate方法进行判断

    这个是 Swift3 新增的方法,使用方便,效率也最高

    func isTheSameDay(startDate: Date, endDate: Date) {
        if Calendar.current.isDate(startDate, inSameDayAs: endDate) {
            print("它们是同一天")
        } else {
            print("它们不是同一天")
        }
    }
    

    参考

    Date
    DateFormatter

    相关文章

      网友评论

          本文标题:iOS - 聊聊时间(Date)

          本文链接:https://www.haomeiwen.com/subject/wdcagftx.html