我在尝试:
NSDate *currentDateInLocal = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:SS.SSS'Z'"];
NSString *currentLocalDateAsStr = [dateFormatter stringFromDate:currentDateInLocal];
NSDateFormatter * dateFormatter2 = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
[dateFormatter2 setTimeZone:timeZone];
[dateFormatter2 setDateFormat:@"yyyy-MM-dd'T'HH:mm:SS.SSS'Z'"];
NSDate *currentDateInUTC = [dateFormatter2 dateFromString:currentLocalDateAsStr];
但它仍然不代表当前的UTC时间,我该如何实现呢?
由于
答案 0 :(得分:51)
你过度复杂了。
NSDate
没有时区或日历。 [NSDate date]
获取当前日期,这是对历史时刻的衡量。如果我在欧洲运行[NSDate date]
与您在美国运行它的时间完全相同,那么我们将获得完全相同的值。
如何打印日期取决于日历和时区。因此,在公历中打印的日期与在儒略历中打印的日期不同。 UTC格里高利历中打印的日期与PST公历中打印的日期不同。但他们仍然是同一个日子。
所以你想直接跳到你的dateFormatter2
。
答案 1 :(得分:42)
NSDate *currentDate = [[NSDate alloc] init];
现在是UTC,(至少在使用下面的方法之后)
要将此时间存储为UTC(自参考日期1970起),请使用
double secsUtc1970 = [[NSDate date]timeIntervalSince1970];
设置日期格式化程序以输出本地时间:
NSTimeZone *timeZone = [NSTimeZone defaultTimeZone];
// or Timezone with specific name like
// [NSTimeZone timeZoneWithName:@"Europe/Riga"] (see link below)
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString *localDateString = [dateFormatter stringFromDate:currentDate];
NSDate
对象始终使用UTC作为时间参考,但日期的字符串表示不一定基于UTC时区。
请注意,UTC不是(仅)一个时区,它是一个系统如何测量地球上的时间,如何协调(UTC中的C代表协调)。
NSDate与UTC时间1.1.1970午夜的参考日期相关,尽管Apple稍微错误地将其描述为1.1.1970 GMT。
在最初的问题中,最后一个词timeZone并不完美。
答案 2 :(得分:38)
接受的answer by Alex Wien 不正确。
默认情况下,NSDateFormatter会将NSDate的日期时间值从UTC调整为用户的本地时区。要防止这种调整,请告诉NSDateFormatter使用UTC
的时区。
要验证结果,请点击“当前时间utc”。
我的源代码应该完成这项工作,这意味着将当前日期时间作为ISO 8601 format(UTC)时区Zulu中的字符串获取,表示为{{1最后。
Z
您可以将此逻辑放在应用程序中的某个便捷方法中。
NSDate* datetime = [NSDate date];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; // Prevent adjustment to user's local time zone.
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString* dateTimeInIsoFormatForZuluTimeZone = [dateFormatter stringFromDate:datetime];
...和...
- (NSString*)now
{
// Purpose: Return a string of the current date-time in UTC (Zulu) time zone in ISO 8601 format.
return [self toStringFromDateTime:[NSDate date]];
}
使用示例......
- (NSString*)toStringFromDateTime:(NSDate*)datetime
{
// Purpose: Return a string of the specified date-time in UTC (Zulu) time zone in ISO 8601 format.
// Example: 2013-10-25T06:59:43.431Z
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString* dateTimeInIsoFormatForZuluTimeZone = [dateFormatter stringFromDate:datetime];
return dateTimeInIsoFormatForZuluTimeZone;
}
或者将这些减号转换为加号以用作类方法而不是实例方法......
NSString* now = [self now];
提示:为了提高人类的可读性,请将格式中的NSString* now = [SomeClassNameHere now];
更改为SPACE。为了通过软件实现更好的互操作性,请保留T
。 ISO 8601规范允许空格,但建议保留T
。
提示:我没有测试过,但是......有人说实例化T
很贵。如果经常这样做(例如在循环中),请考虑缓存单个实例以供重用。
答案 3 :(得分:10)
我还不太晚!因为我看到没有人设置日历标识符。对全球用户来说,非常重要。许多用户使用非公历。他们会错误的一年串。特别是,当您需要将其存储到您自己的数据库中时。 (我们之前遇到过这个问题)
NSCalendarIdentifierGregorian
NSCalendarIdentifierBuddhist
NSCalendarIdentifierChinese
NSCalendarIdentifierHebrew
NSCalendarIdentifierIslamic
NSCalendarIdentifierIslamicCivil
NSCalendarIdentifierJapanese
NSCalendarIdentifierRepublicOfChina
NSCalendarIdentifierPersian
NSCalendarIdentifierIndian
NSCalendarIdentifierISO8601
代码:
-(NSString *)getUTCFormateDate:(NSDate *)localDate
{
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setCalendar:gregorianCalendar];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setLocale:locale];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *dateString = [dateFormatter stringFromDate:localDate];
return dateString;
}
答案 4 :(得分:2)
[NSDate日期]是UTC。也许你被当地人看到了?然后它会转换为您的时区。
如果您在本地时间看到该值,则会在本地时间看到它,但如果您在控制台中打印它,则会以UTC格式看到它。
当您在时间之后看到'+0000'时,您知道它是UTC
答案 5 :(得分:1)
Swift 3
let utcTimestamp = Date().timeIntervalSince1970
print("timeStamp = \(utcTimestamp)")
跟随扩展可能会更容易。
Swift 4 :UTC /GMT⟺本地(当前/系统)
extension Date {
// Convert local time to UTC (or GMT)
func toGlobalTime() -> Date {
let timezone = TimeZone.current
let seconds = -TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}
// Convert UTC (or GMT) to local time
func toLocalTime() -> Date {
let timezone = TimeZone.current
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}
}
// Try it
let utcDate = Date().toGlobalTime()
let localDate = utcDate.toLocalTime()
print("utcDate - (utcDate)")
print("localDate - (localDate)")
答案 6 :(得分:0)
另一种方法是在Objective C项目的C ++类中这样做。 (因此,制作一个.mm文件并使用公共和私有部分构建一个C ++类,并将其粘贴在公共部分(除非您需要私有)。)然后,像NSString *sNowUTC = MyClass::getUTCTimestamp();
一样引用它。
static NSString *getUTCTimestamp(){
time_t rawtime;
struct tm * timeinfo;
char buffer [80];
time (&rawtime);
timeinfo = gmtime (&rawtime);
// make format like "2016-06-16 02:37:00" for
// June 16, 2016 @ 02:37:00 UTC time
strftime (buffer,80,"%F %T",timeinfo);
std::string sTime(buffer);
NSString *sUTC = @(sTime.c_str());
return sUTC;
}
答案 7 :(得分:0)
这就是我使用的。
static func makeISO8601Date(isoDateString: String) -> Date {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return formatter.date(from: isoDateString)
}
makeISO8601Date(isoDateString: "2017-12-31T23:59:59+00:00")