NSDate dateFromString,如何解析“around” UTC、GMT 和用户区域设置?

发布于 2024-08-27 02:09:18 字数 670 浏览 2 评论 0原文

我从 xml 文件中解析一些值。 有一个带有时间和日期的 @"25-12-2010'T'23:40:00" 字符串,还有一个带有 GMT 偏移量的字符串,如 @"+0200"。 所以上面的时间是 12 月 25 日 23:40:00,时区 +0200 GMT。 (或 21:40 世界标准时间) 我有很多这样的日期,它们具有不同的 GMT 偏移量。我必须将这些日期显示为 它们是,即不得更改它们以适应用户的区域设置。因此,如果时间 1: 是 22:45 +0500,那么这就是我必须向用户显示的内容,即使用户位于不同的时区。

我在显示、计算和解析这些字符串时遇到了各种各样的麻烦。

如果我使用 dateFormatter 和 dateFromString ,则用户特定的 GMT 信息将包含在生成的 NSDate 中,这意味着上面的内容将保存为 23:40:00 +0100 GMT,因为是我的手机设置,对于纽约用户的手机来说可能是 23:40:00 −0400。

当我随后在这些日期之间进行减法、加法和比较时,我必须保持 GMT 偏移量,如果手机切换区域设置,从解析日期到显示日期,一切都会变得更糟......

有没有办法让我从字符串中提取该日期作为 UTC,然后将其保存为间隔而不是实际(取决于时区)日期。我知道这就是内部保存日期的方式。但我不知道如何使用单独的 GMT 字符串并考虑用户区域设置来做到这一点。

干杯

I parse some values from an xml file.
There is a @"25-12-2010'T'23:40:00"string with the time and date and there is a string with the GMT offset like this @"+0200".
So the above time is the 25. of December 23:40:00 in timeZone +0200 GMT. (or 21:40 UTC)
I have lots of these dates with different GMT offsets. I have to display these dates as
they are, i.e. They must not be changed to fit the locale of the user. So if time 1: is 22:45 +0500 then that is what I must show the user, even if the user is in a different timezone.

I have all sorts of trouble with displaying, calculating and parsing these strings.

If I use a dateFormatter and dateFromString the user specific GMT info will be included in the resulting NSDate meaning the above will be saved as 23:40:00 +0100 GMT because that is my phones setting and maybe 23:40:00 −0400 on a user from new New York's phone.

When I subsequently do subtraction, addition and comparisons between these dates I have to keep the GMT offset around and everything gets worse if the phone switches locale settings, from when the date was parsed to when the date is displayed...

Is there a way for me to extract this date from the string as UTC, then save it as an interval instead of an actual (timezone dependent) date. I know that is how dates are always saved internally. But I can't figure out how to do it with the separate GMT string and taking into account the users locale.

Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忘你却要生生世世 2024-09-03 02:09:18

使用 NSDateFormatter 的 setTimeZone:。您还需要将时区偏移量与 NSDate 分开存储,以便稍后再次显示这些时区的时间。

Use NSDateFormatter's setTimeZone:. You will also need to store the time zone offsets separately from the NSDate to later display the times in these time zones again.

桃扇骨 2024-09-03 02:09:18

谢谢奥莱。我终于明白了 NSDateNSDateformatter 只是抽象的
概念,并且“日期”在内部真正保存为“自 2001 年 1 月 1 日以来的毫秒或秒”。

我做了一个“概念证明”来真正理解它。现在,在 NSDate 上编写一些类别来确保输入和输出的日期格式正确,突然变得非常简单,但所有计算都是在原始 UTC 日期上完成的。

- (void) testGMTDateParser {

    NSMutableArray *arrayDates = [NSMutableArray arrayWithCapacity:5];
    [self setParsedDates:arrayDates];

    NSMutableArray *arrayGMTOffsets = [NSMutableArray arrayWithCapacity:5];
    [self setParsedGMTOffsets:arrayGMTOffsets]; 

    NSString *date00    = @"2010-03-30T12:00:00";   
    NSString *GMT00     = @"-2";

    NSString *date01    = @"2010-03-30T12:00:00";   
    NSString *GMT01     = @"-1";

    NSString *date02    = @"2010-03-30T12:00:00";   
    NSString *GMT02     = @"+0";

    NSString *date03    = @"2010-03-30T12:00:00";   
    NSString *GMT03     = @"+1";

    NSString *date04    = @"2010-03-30T12:00:00";   
    NSString *GMT04     = @"+2";    

    NSArray *dateArray  = [NSArray arrayWithObjects:date00, date01, date02, date03, date04,nil];
    NSArray *GMTArray   = [NSArray arrayWithObjects:GMT00, GMT01, GMT02, GMT03, GMT04, nil];

    for (int i = 0; i < [dateArray count]; i++) {

        [self parseDateString:[dateArray objectAtIndex:i] withGMTString:[GMTArray objectAtIndex:i]];
    }   

}

解析日期相对于各自的 GMT 偏移量。这将确保保存 UTC 时间
内部是正确的。

-(void) parseDateString:(NSString*) dateString withGMTString:(NSString*) GMTString {

    NSInteger hoursFromGMT      = [GMTString intValue]; 
    NSInteger secondsFromGMT    = (hoursFromGMT * 60 * 60);

    NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:secondsFromGMT];

    NSDateFormatter *dateFormatterGMTAware = [[NSDateFormatter alloc] init];
    [dateFormatterGMTAware setTimeZone:timeZone];
    [dateFormatterGMTAware setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
    NSDate *date = [dateFormatterGMTAware dateFromString:dateString];
    [dateFormatterGMTAware release];

    [self.parsedDates addObject:date];
    [self.parsedGMTOffsets addObject:[NSNumber numberWithInt:secondsFromGMT]];
}

设置 NSDateformatter 以打印与 GMT 偏移有关的保存日期。
现在,所有日期都可以按照 UTC 进行操作,而无需考虑 GMT。

-(void) printOutDates {

    for (int i = 0; i < [self.parsedDates count]; i++) {

        NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:[[parsedGMTOffsets objectAtIndex:i] intValue]];

        NSDateFormatter *dateFormatterGMTAware = [[NSDateFormatter alloc] init];
        [dateFormatterGMTAware setTimeZone:timeZone];
        [dateFormatterGMTAware setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];

        NSLog(@"%@ in Original GMT", [dateFormatterGMTAware stringFromDate:[parsedDates objectAtIndex:i]]);
        NSLog(@"%@ in Local GMT\n\n", [parsedDates objectAtIndex:i]);
    }
}

2010-03-30 18:50:31.284 TimeZonePOC[39830:207] 2010-03-30 12:00:00 -0200(原始 GMT)
2010-03-30 18:50:31.285 TimeZonePOC[39830:207] 2010-03-30 16:00:00 +0200(本地 GMT)

2010-03-30 18:50:31.287 TimeZonePOC[ 39830:207] 2010-03-30 12:00:00 -0100(原始 GMT)
2010-03-30 18:50:31.287 TimeZonePOC[39830:207] 2010-03-30 15:00:00 +0200(本地 GMT)

2010-03-30 18:50:31.289 TimeZonePOC[ 39830:207] 2010-03-30 12:00:00 +0000(原始 GMT)
2010-03-30 18:50:31.289 TimeZonePOC[39830:207] 2010-03-30 14:00:00 +0200(本地 GMT)

2010-03-30 18:50:31.290 TimeZonePOC[ 39830:207] 2010-03-30 12:00:00 +0100(原始 GMT)
2010-03-30 18:50:31.292 TimeZonePOC[39830:207] 2010-03-30 13:00:00 +0200(本地 GMT)

2010-03-30 18:50:31.292 TimeZonePOC[ 39830:207] 2010-03-30 12:00:00 +0200(原始 GMT)
2010-03-30 18:50:31.294 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0200(本地 GMT)

Thank You Ole. I finally got my head around that NSDate and NSDateformatter are just abstract
concepts and that a "date" is truly saved as "milliseconds or seconds since 1/1 2001" internally.

I did a "Proof of concept" to really understand it. Now it is suddenly very simple to write some categories on NSDate that makes sure that dates going in and coming out are correctly formatted, but all calculations are done on the raw UTC date.

- (void) testGMTDateParser {

    NSMutableArray *arrayDates = [NSMutableArray arrayWithCapacity:5];
    [self setParsedDates:arrayDates];

    NSMutableArray *arrayGMTOffsets = [NSMutableArray arrayWithCapacity:5];
    [self setParsedGMTOffsets:arrayGMTOffsets]; 

    NSString *date00    = @"2010-03-30T12:00:00";   
    NSString *GMT00     = @"-2";

    NSString *date01    = @"2010-03-30T12:00:00";   
    NSString *GMT01     = @"-1";

    NSString *date02    = @"2010-03-30T12:00:00";   
    NSString *GMT02     = @"+0";

    NSString *date03    = @"2010-03-30T12:00:00";   
    NSString *GMT03     = @"+1";

    NSString *date04    = @"2010-03-30T12:00:00";   
    NSString *GMT04     = @"+2";    

    NSArray *dateArray  = [NSArray arrayWithObjects:date00, date01, date02, date03, date04,nil];
    NSArray *GMTArray   = [NSArray arrayWithObjects:GMT00, GMT01, GMT02, GMT03, GMT04, nil];

    for (int i = 0; i < [dateArray count]; i++) {

        [self parseDateString:[dateArray objectAtIndex:i] withGMTString:[GMTArray objectAtIndex:i]];
    }   

}

Parse the Dates with regards to their respective GMT offset. This will make sure the UTC time saved
internally is correct.

-(void) parseDateString:(NSString*) dateString withGMTString:(NSString*) GMTString {

    NSInteger hoursFromGMT      = [GMTString intValue]; 
    NSInteger secondsFromGMT    = (hoursFromGMT * 60 * 60);

    NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:secondsFromGMT];

    NSDateFormatter *dateFormatterGMTAware = [[NSDateFormatter alloc] init];
    [dateFormatterGMTAware setTimeZone:timeZone];
    [dateFormatterGMTAware setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
    NSDate *date = [dateFormatterGMTAware dateFromString:dateString];
    [dateFormatterGMTAware release];

    [self.parsedDates addObject:date];
    [self.parsedGMTOffsets addObject:[NSNumber numberWithInt:secondsFromGMT]];
}

Set up the NSDateformatter to print out the saved dates with regards to GMT offset.
all dates can now be manipulated as UTC with no regards to GMT.

-(void) printOutDates {

    for (int i = 0; i < [self.parsedDates count]; i++) {

        NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:[[parsedGMTOffsets objectAtIndex:i] intValue]];

        NSDateFormatter *dateFormatterGMTAware = [[NSDateFormatter alloc] init];
        [dateFormatterGMTAware setTimeZone:timeZone];
        [dateFormatterGMTAware setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];

        NSLog(@"%@ in Original GMT", [dateFormatterGMTAware stringFromDate:[parsedDates objectAtIndex:i]]);
        NSLog(@"%@ in Local GMT\n\n", [parsedDates objectAtIndex:i]);
    }
}

2010-03-30 18:50:31.284 TimeZonePOC[39830:207] 2010-03-30 12:00:00 -0200 in Original GMT
2010-03-30 18:50:31.285 TimeZonePOC[39830:207] 2010-03-30 16:00:00 +0200 in Local GMT

2010-03-30 18:50:31.287 TimeZonePOC[39830:207] 2010-03-30 12:00:00 -0100 in Original GMT
2010-03-30 18:50:31.287 TimeZonePOC[39830:207] 2010-03-30 15:00:00 +0200 in Local GMT

2010-03-30 18:50:31.289 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0000 in Original GMT
2010-03-30 18:50:31.289 TimeZonePOC[39830:207] 2010-03-30 14:00:00 +0200 in Local GMT

2010-03-30 18:50:31.290 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0100 in Original GMT
2010-03-30 18:50:31.292 TimeZonePOC[39830:207] 2010-03-30 13:00:00 +0200 in Local GMT

2010-03-30 18:50:31.292 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0200 in Original GMT
2010-03-30 18:50:31.294 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0200 in Local GMT

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文