NSDate 值总是在我的时区返回
NSDate value is always returned in my time zone
TL/DR:我需要一个 NSDate
具体表示 1970-01-01 00:00:00 +0000
。使用 [NSDate dateWithTimeIntervalSince1970:0]
returns 根据我的时区调整日期。我不知道如何解决这个问题。
我正在尝试编写围绕 NSDates
的 Objective-C iOS 测试。问题是,我尝试创建的任何 NSDate
对象,无论是直的,还是使用 NSDateFormatter
或 [NSDateComponents dateFromComponents]
,似乎总是会针对我的 Mac 当前进行调整时区。也就是说,测试将使用 NSDate 的时区调整值,它也会以这种方式出现在 Xcode 调试器中。但是,如果我在 NSDateComponents
或 NSDateFormatter
中明确将时区设置为 GMT,当我使用 po
检查控制台中的值时,它将 return [=44] =] 像我设置的那样在格林威治标准时间。
例如,[NSDate dateWithTimeIntervalSince1970:0]
return 是日期为 1969-12-31 19:00:00 -0500
的 NSDate。 [NSDate date]
returns 当前日期和时间,但根据我的时区:2015-03-03 05:49:32 -0500
。我想不通为什么我不能简单地将 1970-01-01 00:00:00 +0000
作为 NSDate。
有什么我想念的吗?谁能帮我解决这个问题?
谢谢!
编辑:这是我尝试使用 NSDateComponents
:
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:1970];
[components setMonth:1];
[components setDay:1];
[components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *componentDate = [calendar dateFromComponents:components];
componentDate
在控制台中正确显示(当我键入 po componentDate
时),但在调试 window 中显示为时区调整。此外,这个时区调整后的值是我测试中使用的值,因此它对我编写可靠测试的能力有一定影响。
TLDR:[NSDate dateWithTimeIntervalSince1970:0]
表示您要求的日期。它是将 NSDate
转换为涉及您的时区的字符串。
作为人类,我们有很多方式来表示一个瞬间。例如,“January 1, 2001 00:00:00 GMT”表示一个特定的时间点。同一时刻的另一个名称是“2000 年 12 月 31 日 18:00:00 America/Chicago”。同一时刻的第三个名称是“2001 年 1 月 1 日 03:00:00 Europe/Moscow”。所有这些名称(字符串)以及更多名称都代表同一时刻。作为人类,我们认识到所有这些标签都代表同一时刻。
NSDate
以完全不同的方式表示时间瞬间:NSDate
存储相对于一个预定参考瞬间的偏移量(以秒为单位)。 NSDate
不存储任何时区信息。它只存储一个双精度数。对于每个瞬间,只有一个 NSDate
代表它。1
注意人类表征和 NSDate
表征之间的区别:一个瞬间有许多人类表征,但只有一个 NSDate
表征。
当您在 NSLog
中使用 %@
或在调试器中使用 po
打印日期时,它会向该日期发送 description
消息。 description
方法的工作是为 NSDate
表示的唯一时刻生成一些人类表示。但是有很多可能的人类表示,description
方法只能使用一种。该方法的实施者决定使用基于您当地时区的表示。
如果您不喜欢使用当地时区,请不要使用 description
(直接或间接)。创建一个 NSDateFormatter
,设置它的 timeZone
,根据需要设置它的其他属性,并用它来格式化您的日期。您已经注意到这是可行的。它是您问题的正确解决方案。
如果需要,您可以向 NSDate
添加一个类别,定义 gmtDescription
方法,returns 表示 GMT 日期:
@interface NSDate (Argus9)
- (NSString *)gmtDescription;
@end
@implementation NSDate (Argus9)
- (NSString *)gmtDescription {
static NSDateFormatter *df;
static dispatch_once_t once;
dispatch_once(&once, ^{
df = [[NSDateFormatter alloc] init];
df.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
df.dateFormat = @"yyyy-MM-dd HH:mm:ss";
});
return [df stringFromDate:self];
}
@end
脚注 1。这不完全正确,因为 double
有两个零:+0 和 -0。两者都代表同一时刻(参考时刻本身)。此外,由于 NSDate
将其偏移量存储为 double
,并且双精度数的数量有限,因此它不能唯一地表示每个瞬间。许多时刻映射到相同的 double
值。
TL/DR:我需要一个 NSDate
具体表示 1970-01-01 00:00:00 +0000
。使用 [NSDate dateWithTimeIntervalSince1970:0]
returns 根据我的时区调整日期。我不知道如何解决这个问题。
我正在尝试编写围绕 NSDates
的 Objective-C iOS 测试。问题是,我尝试创建的任何 NSDate
对象,无论是直的,还是使用 NSDateFormatter
或 [NSDateComponents dateFromComponents]
,似乎总是会针对我的 Mac 当前进行调整时区。也就是说,测试将使用 NSDate 的时区调整值,它也会以这种方式出现在 Xcode 调试器中。但是,如果我在 NSDateComponents
或 NSDateFormatter
中明确将时区设置为 GMT,当我使用 po
检查控制台中的值时,它将 return [=44] =] 像我设置的那样在格林威治标准时间。
例如,[NSDate dateWithTimeIntervalSince1970:0]
return 是日期为 1969-12-31 19:00:00 -0500
的 NSDate。 [NSDate date]
returns 当前日期和时间,但根据我的时区:2015-03-03 05:49:32 -0500
。我想不通为什么我不能简单地将 1970-01-01 00:00:00 +0000
作为 NSDate。
有什么我想念的吗?谁能帮我解决这个问题?
谢谢!
编辑:这是我尝试使用 NSDateComponents
:
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:1970];
[components setMonth:1];
[components setDay:1];
[components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *componentDate = [calendar dateFromComponents:components];
componentDate
在控制台中正确显示(当我键入 po componentDate
时),但在调试 window 中显示为时区调整。此外,这个时区调整后的值是我测试中使用的值,因此它对我编写可靠测试的能力有一定影响。
TLDR:[NSDate dateWithTimeIntervalSince1970:0]
表示您要求的日期。它是将 NSDate
转换为涉及您的时区的字符串。
作为人类,我们有很多方式来表示一个瞬间。例如,“January 1, 2001 00:00:00 GMT”表示一个特定的时间点。同一时刻的另一个名称是“2000 年 12 月 31 日 18:00:00 America/Chicago”。同一时刻的第三个名称是“2001 年 1 月 1 日 03:00:00 Europe/Moscow”。所有这些名称(字符串)以及更多名称都代表同一时刻。作为人类,我们认识到所有这些标签都代表同一时刻。
NSDate
以完全不同的方式表示时间瞬间:NSDate
存储相对于一个预定参考瞬间的偏移量(以秒为单位)。 NSDate
不存储任何时区信息。它只存储一个双精度数。对于每个瞬间,只有一个 NSDate
代表它。1
注意人类表征和 NSDate
表征之间的区别:一个瞬间有许多人类表征,但只有一个 NSDate
表征。
当您在 NSLog
中使用 %@
或在调试器中使用 po
打印日期时,它会向该日期发送 description
消息。 description
方法的工作是为 NSDate
表示的唯一时刻生成一些人类表示。但是有很多可能的人类表示,description
方法只能使用一种。该方法的实施者决定使用基于您当地时区的表示。
如果您不喜欢使用当地时区,请不要使用 description
(直接或间接)。创建一个 NSDateFormatter
,设置它的 timeZone
,根据需要设置它的其他属性,并用它来格式化您的日期。您已经注意到这是可行的。它是您问题的正确解决方案。
如果需要,您可以向 NSDate
添加一个类别,定义 gmtDescription
方法,returns 表示 GMT 日期:
@interface NSDate (Argus9)
- (NSString *)gmtDescription;
@end
@implementation NSDate (Argus9)
- (NSString *)gmtDescription {
static NSDateFormatter *df;
static dispatch_once_t once;
dispatch_once(&once, ^{
df = [[NSDateFormatter alloc] init];
df.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
df.dateFormat = @"yyyy-MM-dd HH:mm:ss";
});
return [df stringFromDate:self];
}
@end
脚注 1。这不完全正确,因为 double
有两个零:+0 和 -0。两者都代表同一时刻(参考时刻本身)。此外,由于 NSDate
将其偏移量存储为 double
,并且双精度数的数量有限,因此它不能唯一地表示每个瞬间。许多时刻映射到相同的 double
值。