39

我在尝试:

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时间,我该如何实现呢?

谢谢

4

8 回答 8

53

你把事情复杂化了。

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

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

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

于 2013-01-29T21:41:27.610 回答
43

Alex Wien接受的答案是不正确的。

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

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

我下面的源代码应该可以完成这项工作,这意味着在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];

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

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

……和……</p>

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

使用示例……</p>

NSString* now = [self now];

或者把那些减号变成加号,用作类方法而不是实例方法……</p>

NSString* now = [SomeClassNameHere now];

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


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

于 2013-10-25T06:50:17.110 回答
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];

可用的 NSTimeZone 名称

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

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

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

于 2013-01-29T21:32:19.923 回答
11

请设置日历标识符!

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

NSCalendarIdentifierGregorian
NSCalendarIdentifierBuddhist
NSCalendarIdentifierChinese
NSCalendarIdentifierHebrew
NSCalendarIdentifierIslamic
NSCalendarIdentifierIslamicCivil NSCalendarIdentifierJapanese
NSCalendarIdentifierRepublicOfChina
NSCalendarIdentifier
波斯语
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;
}  
于 2015-11-10T01:29:09.027 回答
3

斯威夫特 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)")
于 2017-06-02T09:55:21.480 回答
2

[NSDate 日期] 是 UTC。也许你被当地人愚弄了?然后它将转换为您的时区。

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

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

于 2013-01-29T21:40:39.303 回答
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")

于 2017-01-26T18:42:12.370 回答
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;
}
于 2016-06-17T02:41:38.407 回答