ios Objective-C,如何获取 UTC 时区的当前日期?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14592556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:03:14  来源:igfitidea点击:

Objective-C, How can I get the current date in UTC timezone?

iosobjective-cnsdatensdateformatter

提问by Baconbeastnz

I am trying:

我在尝试:

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];

but It's still does not represent the current UTC time, how can I achieve this?

但它仍然不代表当前的 UTC 时间,我怎样才能做到这一点?

Thanks

谢谢

回答by Tommy

You're overcomplicating things.

你把事情复杂化了。

NSDates don't have time zones or calendars. [NSDate date]gets the current date, which is a measurement of a moment in history. If I run [NSDate date]in Europe at exactly the same time as you run it in America then we'll get exactly the same value.

NSDates 没有时区或日历。[NSDate date]获取当前日期,这是对历史时刻的度量。如果我[NSDate date]在欧洲跑步的时间和你在美国跑步的时间完全相同,那么我们将获得完全相同的价值。

How you print a date depends on the calendar and the time zone. So a date printed in the Gregorian calendar looks different from the same one printed in the Julian calendar. And a date printed in the UTC Gregorian calendar looks different from the same one printed in the PST Gregorian calendar. But they're still the same date.

打印日期的方式取决于日历和时区。因此,公历中打印的日期看起来与儒略历中打印的日期不同。UTC 公历中打印的日期看起来与 PST 公历中打印的日期不同。但他们仍然是同一个日期。

So you want to jump straight to your dateFormatter2.

所以你想直接跳到你的dateFormatter2.

回答by Basil Bourque

The accepted answer by Alex Wienis incorrect.

Alex Wien接受的答案不正确的

By default, NSDateFormatter adjusts the NSDate's date-time value from UTC to the user's local time zone. To prevent that adjustment, tell the NSDateFormatter to use the time zone for UTC.

默认情况下,NSDateFormatter 将 NSDate 的日期时间值从 UTC 调整为用户的本地时区。为了防止这种调整,告诉 NSDateFormatter 使用UTC.

To verify results, google "current time utc".

要验证结果,请谷歌“当前时间 utc”。

My source code below should do the job, meaning get the current date-time as a string in ISO 8601 formatin the UTC(Zulu) time zone signified by a Zon the end.

我下面的源代码应该可以完成这项工作,这意味着在UTC( Zulu) 时区以ISO 8601 格式的字符串形式获取当前日期时间,最后由 a 表示。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];


You could put this logic in a pair of convenience methods somewhere in your app.

您可以将此逻辑放在应用程序某处的一对便捷方法中。

- (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]];
}

…and…

…和…

- (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;
}

Example of usage…

用法示例…

NSString* now = [self now];

Or turn those minus signs into plus signs to use as class methods rather than instance methods…

或者将这些减号变成加号以用作类方法而不是实例方法......

NSString* now = [SomeClassNameHere now];


Tip: For better readability by humans, change that Tin the format to a SPACE. For better interoperability by software, keep the T. The ISO 8601 spec tolerates a space but recommends keeping the T.

提示:为了提高人类的可读性T,请将其格式更改为空格。为了通过软件获得更好的互操作性,请保留T. ISO 8601 规范允许有空格,但建议保留T.



Tip: I've not tested, but… Some people say instantiating [NSDateFormatter][4]is expensive. If doing so often (such as in a loop) consider caching a single instance for re-use.

提示:我没有测试过,但是……有人说实例化[NSDateFormatter][4]很昂贵。如果经常这样做(例如在循环中),请考虑缓存单个实例以供重用。

回答by AlexWien

NSDate *currentDate = [[NSDate alloc] init];

Now it is in UTC, (at least after using the method below)
To store this time as UTC (since refernce date 1970) use

现在是 UTC,(至少在使用下面的方法之后)
要将这个时间存储为 UTC(自 1970 年以来)使用

double secsUtc1970 = [[NSDate date]timeIntervalSince1970];

Set Date formatter to output local time:

设置日期格式化程序以输出本地时间:

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];

Available NSTimeZone names

可用的 NSTimeZone 名称

A NSDateobject always uses UTC as time reference, but the string representation of a date is not neccessarily based on UTC timezone.

NSDate对象始终使用UTC时间作为参考,但日期的字符串表示不neccessarily基于UTC时区。

Please note that UTC is not (only) a timeZone, It is a system how time on earth is measured, how it is coordinated (The C in UTC stands for coordinated).
The NSDate is related to a reference Date of midnight 1.1.1970 UTC, altough slightly wrongly described by Apple as 1.1.1970 GMT.

请注意,UTC 不是(仅)一个时区,它是一个如何测量地球上的时间、如何协调的系统(UTC 中的 C 代表协调)。
NSDate 与 UTC 午夜 1.1.1970 的参考日期相关,尽管 Apple 稍微错误地将其描述为 1.1.1970 GMT。

In the original question the last word timeZone is not perfect.

在原始问题中,最后一个词 timeZone 并不完美。

回答by Yi Jiang

PLEASE SET UP Calendar Identifier !!!

请设置日历标识符!!!

I am not too late! Because I saw no one set up the Calendar Identifier. It is really importantfor worldwide users. Many users using a non-Gregorian calendar. They will get wrong year string. Especially, when you need store it into your own database. (We met this problem before)

我还不算晚!因为我看到没有人设置Calendar Identifier。这对全球用户来说非常重要。许多用户使用非公历。他们会得到错误的年份字符串。特别是当您需要将其存储到您自己的数据库中时。(我们之前遇到过这个问题)

NSCalendarIdentifierGregorian
NSCalendarIdentifierBuddhist
NSCalendarIdentifierChinese
NSCalendarIdentifierHebrew
NSCalendarIdentifierIslamic
NSCalendarIdentifierIslamicCivil
NSCalendarIdentifierJapanese
NSCalendarIdentifierRepublicOfChina
NSCalendarIdentifierPersian
NSCalendarIdentifierIndian
NSCalendarIdentifierISO8601

NSCalendarIdentifierGregorian
NSCalendarIdentifierBuddhist
NSCalendarIdentifierChinese
NSCalendarIdentifierHebrew
NSCalendarIdentifierIslamic
NSCalendarIdentifierIslamicCivil
NSCalendarIdentifierJapanese
NSCalendarIdentifierRepublicOfChina
NSCalendarIdentifierPersian
NSCalendarIdentifierIndian
NSCalendarIdentifierISO8601

Code:

代码:

-(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;
}  

回答by Cub71

[NSDate date] is UTC. Maybe you get fooled by looking in the locals? Then it gets converted to your timezone.

[NSDate 日期] 是 UTC。也许你会因为看当地人而上当?然后它会转换为您的时区。

If you see the value in the locals, you see it in local time, but if you print it in the console, you see it in UTC.

如果您在 locals 中看到该值,您会在本地时间看到它,但是如果您在控制台中打印它,您会看到它以 UTC 格式显示。

When you see '+0000' after the time, you know it is in UTC

当您在时间之后看到“+0000”时,您就知道它是 UTC

回答by Krunal

Swift 3

斯威夫特 3

let utcTimestamp = Date().timeIntervalSince1970
print("timeStamp = \(utcTimestamp)")

May following extension would be easier.

可能以下扩展会更容易。

Swift 4: UTC/GMT ? Local (Current/System)

斯威夫特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)")

回答by Volomike

Still another way to do it is like so in a C++ class in your Objective C project. (So, make a .mm file and build a C++ class with public and private parts, and stick this in the public part (unless you need it private).) Then, reference it like NSString *sNowUTC = MyClass::getUTCTimestamp();.

还有一种方法是在你的 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;
}

回答by amol-c

This is what i used.

这是我用的。

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")

makeISO8601Date(isoDateString: "2017-12-31T23:59:59+00:00")