iOS NSDate常用的方法及DateFormatter的优化

通过[NSDate date]返回的一定是零时区的时间

    NSDate *date = [NSDate date];
    NSLog(@"date时间 = %@", date);
    //date时间 = 2018-05-31 06:43:07 +0000
    
    //如果没有规定formatter的时区,那么formatter默认的就是当前时区,比如现在在北京就是东八区,在东京就是东九区
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    //最结尾的Z表示的是时区,零时区表示+0000,东八区表示+0800
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
   // 使用formatter转换后的date字符串变成了当前时区的时间
    NSString *dateStr = [formatter stringFromDate:date];
    NSLog(@"字符串时间 = %@", dateStr);
    //字符串时间 = 2018-05-31 14:43:07 +080

上面例子中NSDate时间转字符串时间时,NSDateFormatter并没有设置时区,而是使用当前地区的时区,这和设置系统系统时区
formatter.timeZone = [NSTimeZone systemTimeZone] 的效果是一样的。

转字符串时间的时区设置

   //我们也可以规定一定使用某一个时区:
   NSDate *date = [NSDate date];
   NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
   [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
   formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];//东八区时间
   //这样不管我们的手机是在哪里,打印出来的时间都是东八区的时间
   
   formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Tokyo"];//东九区时间
   formatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];//零区时间
   formatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];//零区时间,和GMT一样
   NSString *dateStr = [formatter stringFromDate:date];
   NSLog(@"字符串时间 = %@", dateStr);

凡是返回结果为NSDate类型的,得到的时间都是零时区

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
    NSDate *newDate = [formatter dateFromString:@"2016-12-07 14:06:24 +0800"];
    NSLog(@"newDate = %@", newDate);
    //newDate = 2016-12-07 06:06:24 +0000
//我们看到这样转化后就出现了问题转后之后得到的时间的时区又变成了零时区。问题就出在,凡是返回结果为NSDate类型的,得到的时间都是零时区,都是零时区!都是零时区!

//闰年2月份是29天

- (NSArray *)getAllWeekDate {//获取今年所有的周
    
    NSDate *nowDate = [NSDate date];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comp = [calendar components: NSCalendarUnitWeekday | NSCalendarUnitWeekOfYear fromDate:nowDate];
    // 获取今天是周几 (周一是2,周日是1)
    NSInteger weekDay = [comp weekday];
    //这周是今年的第几周(注意:第一周编号为1不为0)
    NSInteger weekOfYear = [comp weekOfYear];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyyMMdd"];
    NSDate *date = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]];
    //这周的开始和结束时间 (注意:+1 -1 避开临界值)
    NSDate *startdate = [date dateByAddingTimeInterval:24*3600*(2 - weekDay)+1];
    NSDate *enddate = [date dateByAddingTimeInterval:24*3600*(9 - weekDay)-1];
    NSMutableArray *dateArray = [[[NSMutableArray alloc] init] mutableCopy];
    //一年52周  获取一年的所有周一和周日的日期(注意:第一周编号为1不为0)
    for (int i = 1; i <= 52; i++) {
        NSDate *startdate1 = [startdate dateByAddingTimeInterval:24*3600*7*(i-weekOfYear)];
        NSDate *enddate1 = [enddate dateByAddingTimeInterval:24*3600*7*(i-weekOfYear)];
        [dateArray addObject:@[startdate1,enddate1]];
    }
    
    return dateArray;
}

指定日期是年的第几周 月的第几周 星期几

    NSDate *showDate = [NSDate date];
    NSCalendar*calendar = [NSCalendar currentCalendar];
    NSDateComponents *comps =[calendar components:(NSCalendarUnitWeekOfYear | NSCalendarUnitWeekday |NSCalendarUnitWeekdayOrdinal) fromDate:showDate];
    NSInteger week = [comps weekOfYear]; // 今年的第几周
    NSInteger weekday = [comps weekday]; // 星期几(注意,周日是“1”,周一是“2”。。。。)
    NSInteger weekdayOrdinal = [comps weekdayOrdinal]; // 这个月的第几周

当前日期所在周的周一 和 周日

/**
 获取指定日期的周一 和 周末的日期

 @param date 某一日期
 @return @“10.13-10.19”
 */
+ (NSString *)weekTimeForDate:(NSDate *)date {
    
    NSDate *nowDate = date;
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday  fromDate:nowDate];
    // 获取今天是周几
    NSInteger weekDay = [comp weekday];
    // 获取几天是几号
    NSInteger day = [comp day];
    NSLog(@"周几 %ld---- 几号 %ld",(long)weekDay,(long)day);
    
    // 计算当前日期和本周的星期一和星期天相差天数
    long firstDiff,lastDiff;
    //    weekDay = 1; weekDay == 1 == 周日
    if (weekDay == 1) {
        firstDiff = -6;
        lastDiff = 0;
    }
    else {
        firstDiff = [calendar firstWeekday] - weekDay + 1;
        lastDiff = 8 - weekDay;
    }
    NSLog(@"firstDiff: %ld   lastDiff: %ld",firstDiff,lastDiff);
    
    // 在当前日期(去掉时分秒)基础上加上差的天数
    NSDateComponents *baseDayComp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay  fromDate:nowDate];
    
    //获取周一日期
    [baseDayComp setDay:day + firstDiff];
    NSDate *firstDayOfWeek = [calendar dateFromComponents:baseDayComp];
    
    //获取周末日期
    [baseDayComp setDay:day + lastDiff];
    NSDate *lastDayOfWeek = [calendar dateFromComponents:baseDayComp];
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//    [formatter setDateFormat:@"YYYY年MM月dd日"];
    [formatter setDateFormat:@"MM.dd"];
    NSString *firstDay = [formatter stringFromDate:firstDayOfWeek];
    NSString *lastDay = [formatter stringFromDate:lastDayOfWeek];
    NSLog(@"%@=======%@",firstDay,lastDay);
    NSString *dateStr = [NSString stringWithFormat:@"%@-%@",firstDay,lastDay];
    
    return dateStr;
}

NSDate与字符串互相转换


NSDate --> NSString
//获取当前时间
NSDate *date = [NSDate date];
//设置日期格式
NSDateFormatter* formatter1 = [[NSDateFormatter alloc] init];
[formatter1 setDateFormat:@"yyyyMMddHHmmss"];
//变为数字
NSString* str = [formatter1 stringFromDate:date];

NSString --> NSDate
//时间字符串
NSString *str = @"20150806070733";
//规定时间格式
NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyyMMddHHmmss"];
//设置时区  全球标准时间CUT 必须设置 我们要设置中国的时区
NSTimeZone *zone = [[NSTimeZone alloc] initWithName:@“CUT"];
[formatter setTimeZone:zone];
//变回日期格式
NSDate *stringDate = [formatter dateFromString:str];
NSLog(@"stringDate = %@",stringDate);

比较两个日期的大小

https://blog.csdn.net/hong1595/article/details/44975375

日期格式请传入:2013-08-05 12:12:12;如果修改日期格式,比如:2013-08-05,则将[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];修改为[dateformater setDateFormat:@"yyyy-MM-dd"];
/**
 比较两个日期的大小 0 相等; 1 后者大于前者; -1 前者大于后者
 
 @param aDate 日期A
 @param bDate 日期B
 @return 0 相等; 1 B > A; -1 A > B
 */
+ (NSInteger)compareWithADate:(NSString*)aDate bDate:(NSString*)bDate {
    
    NSInteger value = 0;
    NSDateFormatter *dateformater = [[NSDateFormatter alloc] init];
    [dateformater setDateFormat:@"yyyy-MM-dd"];
    NSDate *dta = [[NSDate alloc] init];
    NSDate *dtb = [[NSDate alloc] init];
    
    dta = [dateformater dateFromString:aDate];
    dtb = [dateformater dateFromString:bDate];
    NSComparisonResult result = [dta compare:dtb];
    if (result == NSOrderedSame) {
        //        相等  aa=0
    }
    else if (result == NSOrderedAscending) {
        //bDate比aDate大
        value = 1;
    }
    else if (result == NSOrderedDescending) {
        //bDate比aDate小
        value = -1;
    }
    
    return value;
}

判断日期是星期几

- (NSString *)weekdayStringWithDate:(NSDate *)date {
    //获取星期几
    NSDateComponents *componets = [[NSCalendar autoupdatingCurrentCalendar] components:NSCalendarUnitWeekday fromDate:date];
    NSInteger weekday = [componets weekday];//1代表星期日,2代表星期一,后面依次
    NSArray *weekArray = @[@"星期日",@"星期一",@"星期二",@"星期三",@"星期四",@"星期五",@"星期六"];
    NSString *weekStr = weekArray[weekday-1];
    return weekStr;
}

判断日期与今天是否在同一周

https://www.jianshu.com/p/9236d6cb9d09

NSCalendar自带方法判断日期是否是今天

+ (NSString *)checkTheDate:(NSString *)string{

NSDateFormatter *format = [[NSDateFormatter alloc]init];
[format setDateFormat:@"yyyy-MM-dd"];
NSDate *date = [format dateFromString:string];
BOOL isToday = [[NSCalendar currentCalendar] isDateInToday:date];
NSString *strDiff = nil;

if(isToday) {
    strDiff= [NSString stringWithFormat:@"今天"];
}
return strDiff;
}

获取当前时间若干年、月、日之后的时间

+ (NSDate *)dateWithFromDate:(NSDate *)date years:(NSInteger)years months:(NSInteger)months days:(NSInteger)days{
    NSDate  * latterDate;
    if (date) {
        latterDate = date;
    }else{
        latterDate = [NSDate date];
    }
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSDateComponents *comps = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute
                                          fromDate:latterDate];

    [comps setYear:years];
    [comps setMonth:months];
    [comps setDay:days];

    return [calendar dateByAddingComponents:comps toDate:latterDate options:0];
}

两个日期之间的相差的天数

/**
 * @method
 *
 * @brief 获取两个日期之间的天数
 * @param fromDate       起始日期
 * @param toDate         终止日期
 * @return    总天数
 */
+ (NSInteger)numberOfDaysWithFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate{
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    NSDateComponents    * comp = [calendar components:NSCalendarUnitDay
                                             fromDate:fromDate
                                               toDate:toDate
                                              options:NSCalendarWrapComponents];
    NSLog(@" -- >>  comp : %@  << --",comp);
    return comp.day;
}

NSDateFormatter的优化

NSDateFormatter是线程安全的,因此我们无需担心日期格式化对象在使用过程中被另外一条线程给修改

static NSDateFormatter *cachedDateFormatter = nil;

+ (NSDateFormatter *)cachedDateFormatter {

if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setDateFormat: @"YYYY-MM-dd HH:mm:ss"];
}

return dateFormatter;
}

//使用
NSString* str = [cachedDateFormatter stringFromDate:date];

无法分析出具体是哪一步骤是主要耗时的,但是在项目中,如果使用单例来对创建,设置日期格式这两个步骤来缓存,使用Instrument进行分析时确实可以将运行时间降为不缓存时的10%左右

  • 使用C语言的api来进行时间转换
size_t   strftime_l(char * __restrict, size_t, const char * __restrict,
        const struct tm * __restrict, locale_t)
        __DARWIN_ALIAS(strftime_l) __strftimelike(3);
//使用C语言来做日期处理
-(void)testDateFormatterInC:(NSInteger)times {
    NSString *string = @"";
    NSDate *date;
    time_t timeInterval;
    char buffer[80];
    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
    for (int i=0; i

对于iOS开发的同学来说比较陌生的就是
strftime_l(buffer, sizeof(buffer), "%Y年%m月%d日%H时%M分%S秒", localtime(&timeInterval), NULL);
这这行代码的调用,strftime_l函数接受四个参数,

  1. 第一个参数buffer是C语言中字符数组用于存储日期格式化后的字符串,
  2. 第二个参数是写入buffer数组的最大值,如果格式化的字符串大于这个值,那么只会取字符串的的一部分,
  3. 第三个参数"%Y年%m月%d日%H时%M分%S秒"是日期格式,
  4. 第四个参数localtime(&timeInterval)是指向使用当地时区对时间戳处理得到tm类型结构体的指针

iOS中对时间的理解

NSDateFormatterd优化-1
NSDateFormatterd优化-2

日历代码参考
http://code.cocoachina.com/view/136634

你可能感兴趣的:(iOS NSDate常用的方法及DateFormatter的优化)