美文网首页
iOS 时间字符串,日历,格式化,东八

iOS 时间字符串,日历,格式化,东八

作者: Yuency | 来源:发表于2021-06-28 11:43 被阅读0次

前言:

公司的App有海外用户。这些海外用户他们手机的时间,可不一定都是北京时间,有在美国的,有在英国的,有在日本的。

因为用户所处时区不一样,所以,每个手机的时间各不相同。然而我们服务器下发的时间,是北京时间。

这就有一个潜在问题:服务器下发的时间是北京时间上午9:00整开始上课,美国那边的用户打开手机看到的时间可不是上午9:00点,除非他自己去看北京时钟。

需求:无论用户处在哪个时区,打开我们的App,我们App里的时间,是和北京时间同步的。

代码地址:https://github.com/gityuency/ObjectiveCTools
示例代码类名 【AboutTimeViewController】

直接上结论代码,Command + C,V

//不管你的手机当前在哪个时区,也不管从 NSDate 还是 NSCalendar 里去获取时间,我都要拿到正确的东八时间,和服务器(服务器就在北京,给出的时间就是东八时间)给的时间做比较,方便接下来的时间逻辑。
- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *timestring = @"2020-06-28 10:30";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:8]];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
    NSDate *dateServer = [formatter dateFromString:timestring];
    NSLog(@"服务器时间(转东八): %@", dateServer);
 
    
    NSDate *datePhone = [NSDate date];
    NSTimeZone *GMT8Zone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"];
    NSInteger interval = [GMT8Zone secondsFromGMTForDate:datePhone];
    NSDate *localGTM8Date = [datePhone dateByAddingTimeInterval: interval];
    NSLog(@"手机当前时间(转东八): %@",localGTM8Date);

    
    NSCalendar *calendar = [NSCalendar currentCalendar];
    [calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:8]];
    NSUInteger unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute;
    NSDateComponents *com1 = [calendar components:unitFlags fromDate:dateServer];
    NSString *calendarServertime = [NSString stringWithFormat:@"今日%ld月%ld日 %ld时%ld分",(long)com1.month,(long)com1.day,(long)com1.hour,(long)com1.minute];
    NSLog(@"服务器日历时间(转东八): %@", calendarServertime);
    
    
    //NSCalendar *calendar = [NSCalendar currentCalendar];
    [calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"]];
    //NSUInteger unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute;
    NSDateComponents *com2 = [calendar components:unitFlags fromDate:datePhone];
    NSString *calendarPhonetime = [NSString stringWithFormat:@"今日%ld月%ld日 %ld时%ld分",(long)com2.month,(long)com2.day,(long)com2.hour,(long)com2.minute];
    NSLog(@"手机当前日历时间(转东八): %@", calendarPhonetime);
}


输出

ObjectiveCTools[1475:816321] 服务器时间(转东八): 2020-06-28 10:30:00 +0000
ObjectiveCTools[1475:816321] 手机当前时间(转东八): 2020-06-28 10:34:11 +0000
ObjectiveCTools[1475:816321] 服务器日历时间(转东八): 今日6月28日 10时30分
ObjectiveCTools[1475:816321] 手机当前日历时间(转东八): 今日6月28日 10时34分

以下是关于时间,日历,和格式化的尝试代码,不加修饰,有时候是搞出乱子的,还得是格式化,设置时区之后才好用

问题:1、如果单纯只拿时间,那么不会有错,如果加上中文,就有内鬼

可以看到差了8小时。然而写代码的时候,我并不希望出现这么个无聊的8小时问题啊。

- (void)viewDidLoad {
    [super viewDidLoad];

    [self demo0]; //当前时区在北京
}

- (void)demo0 {
    NSDate *datePhone = [NSDate date];
    NSLog(@"%@", datePhone);
    NSLog(@"加上中文 %@", datePhone);
}

输出
ObjectiveCTools[1367:790862] Mon Jun 28 10:29:26 2020
ObjectiveCTools[1367:790862] 加上中文 2020-06-28 02:29:26 +0000

问题:2、如果从服务器拿到时间字符串,直接转换成SDadate,也还是有内鬼

同样是差了8小时,然而写代码的时候,我并不希望出现这么个无聊的8小时。

- (void)viewDidLoad {
    [super viewDidLoad];

    [self demo1];
}


- (void)demo1 {
    //当前时间是 2020-06-28 10:30 (上午十点半)
    
    NSDate *datePhone = [NSDate date];
    NSLog(@"北京时区 手机时间: %@", datePhone);
    
    NSString *timestring = @"2020-06-28 10:30";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
    NSDate *dateServer = [formatter dateFromString:timestring];
    NSLog(@"北京时区 服务器时间: %@", dateServer);
}

输出
ObjectiveCTools[1371:792380] 北京时区 手机时间: 2020-06-28 02:33:46 +0000
ObjectiveCTools[1371:792380] 北京时区 服务器时间: 2020-06-28 02:30:00 +0000

解决 1、2、 给formatter加上时区就可以了。即便这时候你切换了手机的时区,从北京换到纽约,字符串的时间格式化结果仍然是正常的。

- (void)viewDidLoad {
    [super viewDidLoad];

    [self demo1];
}


- (void)demo1 {
    //当前时间是 2020-06-28 10:30 (上午十点半)
    
    NSDate *datePhone = [NSDate date];
    NSLog(@"北京时区 手机时间: %@", datePhone);
    
    NSString *timestring = @"2020-06-28 10:30";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    //给 formatter 加上时区
    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:8]];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
    NSDate *dateServer = [formatter dateFromString:timestring];
    NSLog(@"北京时区 服务器时间: %@", dateServer);
}

输出
ObjectiveCTools[1388:796545] 北京时区 手机时间: 2020-06-28 02:31:08 +0000
ObjectiveCTools[1388:796545] 北京时区 服务器时间: 2020-06-28 10:30:00 +0000

将NSDate设置时区东八。如果要使用当前的NSDate,并且不管手机设置为什么时区,都要取得当前的东八时间,和服务器做比较。

- (void)viewDidLoad {
    [super viewDidLoad];

    [self demo2];
}


- (void)demo2 {
    //当前时间是 2020-06-28 10:30 (上午十点半)
    
    NSDate *datePhone = [NSDate date];
    NSLog(@"美国费城 原始 手机时间: %@", datePhone); //输出错误,费城此时应该是 6月27号
    
    NSString *timestring = @"2020-06-28 10:30";
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    //给 formatter 加上时区
    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:8]];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
    NSDate *dateServer = [formatter dateFromString:timestring];
    NSLog(@"北京 服务器时间: %@", dateServer);
 
    
    //格式化本地时间,设置时区
    NSTimeZone *GMT8Zone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"];
    //NSTimeZone *GMT8Zone = [NSTimeZone timeZoneForSecondsFromGMT:8]; //不要用这句,有毒
    NSInteger interval = [GMT8Zone secondsFromGMTForDate:datePhone];
    NSDate *localGTM8Date = [datePhone dateByAddingTimeInterval: interval];
    NSLog(@"美国费城 格式化 手机时间: %@",localGTM8Date);
    
}

输出
ObjectiveCTools[1414:803611] 美国费城 原始 手机时间: 2020-06-28 02:48:28 +0000
ObjectiveCTools[1414:803611] 北京 服务器时间: 2020-06-28 10:30:00 +0000
ObjectiveCTools[1414:803611] 美国费城 格式化 手机时间: 2020-06-28 10:48:28 +0000

使用到日历来获取时间的时候,也有需要格式化设定时区的场景。后面不写了,代码直接抄就行。

结语

就这么一个小小的时间。

相关文章

网友评论

      本文标题:iOS 时间字符串,日历,格式化,东八

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