金沙国际平台登录-金沙国际会员登录

热门关键词: 金沙国际平台登录,金沙国际会员登录

但是有的时候我们或许也会使用到,我们就需要

问题:

在数据库搬砖的过程中,免不了要跟日期打交道,比如按日期汇总一些指标、统计某段时间内的总量等。

在iOS中,我们处理时间的时候,往往会使用到NSDate这个类,但是有的时候我们或许也会使用到NSCalendar这个类,下面就先简单介绍下NSDate这个类。

在数据库编程开发中,有时需要获取一年前的日期,以便以此为时间的分界点,查询其前后对应的数据量。例如:

如果是固定的日期还好,只需直接指定即可,但很多时候都是需要根据当前日期自适应变化的。比如:提取上周一到上周日的数据、提取上个月的数据、提取前N个月的数据。。。

NSDate和字符串的相互转换

1. 想查询截止到一年前当天0点之前的数据量,以及一年前当天0点开始到现在的数据量。2. 想查询截止到一年前当天24点之前的数据量,以及一年前当天24点开始到现在的数据量。3. 想查询截止到一年前当月1日0点之前的数据量,以及一年前当月1日0点开始到现在的数据量。4. 想查询截止到一年前当月最后一天24点之前的数据量,以及一年前当月最后一天24点开始到现在的数据量。

这些要求都有一个共同点,就是要视当前日期而定!那么,我们就需要首先获取当前日期的一些信息,如当前日期是本周第几天、本月第几天等,然后,才能做下一步处理。

1.将字符串转为带格式的日期

  • 字符串有规则的样式
void string2date() {
    // 时间字符串
    NSString *string = @"2015-11-20 09:33:22";
    // 日期格式化类
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 设置日期格式(为了转换成功)
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // NSString * -> NSDate *
    NSDate *date = [fmt dateFromString:string];
    NSString *newStr = [fmt stringFromDate:date];
    NSLog(@"%@", date);
    NSLog(@"%@", newStr);
}
// 打印结果
2016-10-20 01:33:22 +0000
2016-10-20 09:33:22

可以看出以上的打印结果是有八个小时的时差,这是由于上面的date所表示的区域是格林威治时间,我们处于的是东八区。

  • 字符串的样式不规则

以上的字符串是有着比较规则的样式,假如有的服务器返回的结果是比较混乱的话,在对日期的格式样式重新设置的话也是可以得到的想要的数据。

void string2date2() {
    // 时间字符串
    NSString *string = @"10月-20号/2016年 09-10:05秒";
    // 日期格式化类
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"MM月-dd号/yyyy年 HH-mm:ss秒";
    NSLog(@"%@", [fmt dateFromString:string]);
}
// 打印结果
2016-10-20 01:10:05 +0000
  • 当字符串中有英文的表达样式
void string2date3() {
    // 时间字符串
    NSString *string = @"Tue May 31 17:46:55 +0800 2011";
    // 日期格式化类
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
    // fmt.dateFormat = @"EEE MMM dd HH:mm:ss ZZZZ yyyy";
    // 设置语言区域(因为这种时间是欧美常用时间)
    fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
    NSLog(@"%@", [fmt dateFromString:string]);
}
// 打印结果
2016-05-31 09:46:55 +0000

上面的代码中的EEE表示的是星期的缩写,MMM表示的月份的缩写,其中的ZZZZZ表示的是时区。

  • 时间戳样式

有时候服务器返回我们的字符串不一定是以上的规则的样式或者是不规则样式的字符串,返回给我们就是一长串的数字,这就是时间戳,其意思是距离1970年1月1日0点0分0秒的时间,单位是

void string2date4() {
    // 时间戳 : 从1970年1月1号 00:00:00开始走过的秒数
    // 时间字符串 - 时间戳
    NSString *string = @"1745645645645";
    // 转为秒为单位
    NSTimeInterval second = string.longLongValue / 1000.0;
    // 时间戳 -> NSDate *
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:second];  
    NSLog(@"%@", date);
}
// 打印结果
2025-04-26 05:34:05 +0000

以上这四种情况的具体查询场景,有archive数据脚本开发之前对数据库数据量的分布情况进行统计等,也有根据当前日期动态计算一年来的增量增幅情况等。

一、在提取所需日期区间之前,我们先介绍几个常用的函数

2.日期转为字符串

  • 转为有固定格式的字符串
void date2string() {
    // 获取当前的时间
    NSDate *date = [NSDate date];
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 给转换的字符串一个固定格式
    fmt.dateFormat = @"yyyy年MM月dd号 HH:mm:ss";
    NSString *string = [fmt stringFromDate:date];
    NSLog(@"----%@+++++", string);  
}
// 打印结果
----2016年10月24号 16:19:42+++++

在以上的代码中需要特别值得注意的是给字符串一个固定的格式,不然转换成的字符串就不知道以何种格式展示出来,打印出来为空。

如果每次接到这样的需求需要获取一年前日期,然后每次重新思考怎么去实现肯定是不明智的,或者说公司内已经有人写了脚本实现,但其他同事遇到相同的问题,又重新构思一次,这样就比较浪费时间和精力,耗在这个细节上一些精力,有点像要做饭可是没有米就要先去买米的感觉,而且容易造成不同人写的脚本不统一,不利于代码规范化标准化的原则,不同的人跟进的时候还要去想想之前的人写的是什么逻辑。而且重新开发脚本的话,又需要重新进行自测,不利于提高工作效率。

-- 先运行这一句SET @t = '2018-07-26 11:41:29';-- 再运行这一句SELECT DATE(@t)当前日期,YEAR(@t) 年份, MONTH(@t)月份,WEEK(@t)本年第几周, DAY(@t) 本月第几天, HOUR(@t)小时, MINUTE(@t)分钟, SECOND(@t)秒

获取到日期的年月日时分秒

有的时候我们其实只需要获取到时间中的年月日等元素,这时候就需要抽取时间元素中一些子元素。
如果返回的字符串的格式是规则的话就可以用定位的方式就可以截取到其中想要的元素。

void getComponentsOfDate() {
    // 时间字符串
    NSString *string = @"2016-10-20 09:10:05";
    NSString *month = [string substringWithRange:NSMakeRange(5, 2)];
    NSLog(@"%@", month);
}
// 打印结果
10

这样是可以截取到想要的结果,但是如果我想得到时间中所有的元素,就要重复多次这样的代码,这样就比较麻烦,所以不建议使用。我们可以考虑使用NSCalendar这个类中的方法去截取时间中的所有元素。

void getComponentsOfDate2() {
    // 时间字符串
    NSString *string = @"2016-10-20 09:10:05";
    // 日期格式化类
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 设置日期格式(为了转换成功)
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // NSString * -> NSDate *
    NSDate *date = [fmt dateFromString:string];
    // 利用NSCalendar处理日期
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
    NSInteger hour = [calendar component:NSCalendarUnitHour fromDate:date];
    NSInteger minute = [calendar component:NSCalendarUnitMinute fromDate:date];
    NSLog(@"%zd %zd %zd", month, hour, minute);
}
// 打印结果
10 09 10

假如要一次性得到时间中的所有元素就可以考虑使用NSCalendarUnit类去得到时间中年月日等元素,这些都是可以用或运算进行操作的。

void getComponentsOfDate3() {
    // 时间字符串
    NSString *string = @"2016-10-20 09:10:05";
    // 日期格式化类
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 设置日期格式(为了转换成功)
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // NSString * -> NSDate *
    NSDate *date = [fmt dateFromString:string];
    // 利用NSCalendar处理日期
    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *cmps = [calendar components:unit  fromDate:date];
    //    NSLog(@"%zd %zd %zd", cmps.year, cmps.month, cmps.day);
    NSLog(@"%@", cmps);
}
// 打印结果
<NSDateComponents: 0x101018c10>
    Calendar Year: 2016
    Month: 10
    Leap month: no
    Day: 20
    Hour: 9
    Minute: 10
    Second: 5

通过以上的unit可以取到想要的元素,放到NSDateComponents中打印出来。

解决方案:

运行出来,结果是这样的:

时间的比较

往往有的时候会用到时间与时间的相互比较,例如微博中,一条微博的发布,会显示是什么时候发布的,如:“刚刚”、“一个小时前”等,这需要用到发布时间和当前时间的比较,并且通过一系列的判断展示到界面上去。

  • 简单比较
void dateCompare() {
    // 时间字符串
    NSString *createdAtString = @"2015-11-20 11:10:05";
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *createdAtDate = [fmt dateFromString:createdAtString];

    // 手机当前时间
    NSDate *nowDate = [NSDate date];

    /**
     NSComparisonResult的取值
     NSOrderedAscending = -1L, // 升序, 越往右边越大
     NSOrderedSame,  // 相等
     NSOrderedDescending // 降序, 越往右边越小
     */
    // 获得比较结果(谁大谁小)
    NSComparisonResult result = [nowDate compare:createdAtDate];
    if (result == NSOrderedAscending) { // 升序, 越往右边越大
        NSLog(@"createdAtDate > nowDate");
    } else if (result == NSOrderedDescending) { // 降序, 越往右边越小
        NSLog(@"createdAtDate < nowDate");
    } else {
        NSLog(@"createdAtDate == nowDate");
    }
}
// 打印结果
createdAtDate < nowDate

以上只能比较出两个日期之前的先后或者是否为同一个时间,但是不能真实的比较出两个时间之间相差的时间;

  • 间隔时间
void dateCompare2() {
    // 时间字符串
    NSString *createdAtString = @"2016-11-20 09:10:05";
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *createdAtDate = [fmt dateFromString:createdAtString];

    // 手机当前时间
    //    NSDate *nowDate = [NSDate date];

    // 获得createdAtDate和nowDate的时间间隔(间隔多少秒)
    //    NSTimeInterval interval = [nowDate timeIntervalSinceDate:createdAtDate];
    NSTimeInterval interval = [createdAtDate timeIntervalSinceNow];
    NSLog(@"%f", interval);
}
// 打印结果
2305313.187479 
// 正表示当前时间之后的时间,负表示当前时间之前的时间。

timeIntervalSinceDate:表示一个时间到另一个时间的相隔的时间;
timeIntervalSinceNow表示的是一个时间到现在时间之间相隔的时间。

  • 高级比较

以上的结果是可以得到两个相比较的时间之间的间隔时间,但是并不能很好的反应出到底是相差多少天或者是多少个月,可以借助到NSCalendar中的一些方法可以解决上述的问题。

void dateCompare3() {
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";

    // 时间字符串
    NSString *createdAtString = @"2015-11-01 09:10:05";
    NSDate *createdAtDate = [fmt dateFromString:createdAtString];
    // 其他时间
    NSString *otherString = @"2015-10-31 08:56:45";
    NSDate *otherDate = [fmt dateFromString:otherString];
    // 获得NSCalendar
    NSCalendar *calendar = nil;
    // 这个判断主要是由于iOS版本的限制,`calendarWithIdentifier: `这个方法是iOS8.0之后开始使用的
    if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
        calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
    } else {
        calendar = [NSCalendar currentCalendar];
    }

    // 获得日期之间的间隔
    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *cmps = [calendar components:unit fromDate:createdAtDate toDate:otherDate options:0];  
    NSLog(@"%@", cmps);
}
// 打印结果
<NSDateComponents: 0x10060a5e0>
    Calendar Year: 0
    Month: 0
    Day: -1
    Hour: 0
    Minute: -13
    Second: -20

从打印的结果可以清楚的看出两个时间之间的相差多少日、时、分、秒等。

首先简单介绍一下基本的知识点:

二、下面介绍几个常用的日期加减运算函数

判断是否为今天、昨天等

有的时候需要判断当前的日期是否今天或者是在当月等的需求,这就需要作出判断。

getdate()是获取当前日期;dateadd可以对日期进行增减,在这里用来对年份减少1,也可以用来对月份增加1;convert可以对日期进行字符串截取转换操作,在这里可以只截取形如2019-07-17的年月日,也可以只截取形如2019-07的年月部分。

1、ADDDATE(expr, days) / SUBDATE(expr, days):

金沙国际平台登录,系统方法

void judgeToday() {
    // 获得NSCalendar
    NSCalendar *calendar = nil;
    if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
        calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
    } else {
        calendar = [NSCalendar currentCalendar];
    }    
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSLog(@"%zd", [calendar isDateInToday:[fmt dateFromString:@"2015-11-10 01:09:56"]]);  
}

以上的打印结果为0,所以得知不是今天

// 今天的判断
- (BOOL)isDateInToday:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 昨天的判断
- (BOOL)isDateInYesterday:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 明天的判断
- (BOOL)isDateInTomorrow:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 周末的判断
- (BOOL)isDateInWeekend:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 是否为同一天
- (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2 NS_AVAILABLE(10_9, 8_0);

可以看出上面的代码都是iOS8.0之后出现的,所以在iOS8.0之前的版本是适用不了的,如果想要得到判断的话就需要自己去封装,其中还是需要用到NSCalendar这个类,因为这个类可以取到时间中的所有元素。

然后就是针对上面4个问题对应的4个解决方法:

ADDDAT函数有两个形参,第一个是基准日期,也即需要运算的日期;第二个是一个间隔表达式,形如:INTERVAL 1 HOUR,其中INTERVAL 是间隔的意思,中间的数字1可以换成任意整数,第三个hour可以替换成day/month/year等时间单位。

自定义封装

  • 判断今天
- (BOOL)isToday {
    // 判断self这个日期是否为今天
    NSCalendar *calendar = [NSCalendar calendar];  
    // 获得年月日元素
    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
    // 获取到self这个日期中所有的元素
    NSDateComponents *selfCmps = [calendar components:unit fromDate:self];
     // 获取到`现在`这个日期中的所有元素
    NSDateComponents *nowCmps = [calendar components:unit fromDate:[NSDate date]];
    return selfCmps.year == nowCmps.year
    && selfCmps.month == nowCmps.month
    && selfCmps.day == nowCmps.day;
}
  • 判断昨天或是明天
NSDateComponents *cmps = [calendar components:unit fromDate:selfDate toDate:nowDate options:0];
return cmps.year == 0
    && cmps.month == 0
    // 1代表昨天,-1代表明天(具体的还是要看具体代码的逻辑)
    && cmps.day == -1;// 1

总结:
1.在NSDate这个类中可以对字符串转换成date数据,对转换成的字符串的格式是有要求的。
2.时间戳的处理,要看清楚服务器返回的字符串的位数,要仔细处理时间戳的单位。
3.NSCalendar这个类中可以对时间的处理有些比较高端的处理,有些功能是NSDate处理不了的。但是如果在iOS 8.0之前,有些用法是需要自定义封装的。
4.写的不对的地方,还望大家直接指出,小弟不胜感激。

  1. 最简单,对当前日期进行减少1年的运算,然后只截取年月日。2. 先对当前日期进行增加1天的运算,然后再减少1年,最后只截取年月日。3. 先对当前日期进行截取年月操作,然后再指定为当月01日,再减少1年,最后只截取年月日。4. 先对当前日期进行截取年月操作,然后再指定为当月01日,再减少1年,并加上1个月,最后只截取年月日。

SUBDATE同理,只不过变成了减法运算。

本文由金沙国际平台登录发布于金沙国际平台登录,转载请注明出处:但是有的时候我们或许也会使用到,我们就需要

您可能还会对下面的文章感兴趣: