【问题标题】:NSDate Format outputting wrong dateNSDate 格式输出错误的日期
【发布时间】:2015-06-28 10:10:11
【问题描述】:

我有一个 NSString(例如“2011-04-12 19:23:39”),我将其格式化为 NSDate 的操作如下:

[inputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSDate *date = [inputFormatter dateFromString:newDateString];

但是当我 nslog 日期时它输出的是这样的:

2011-04-12 23:23:39 +0000

大约要休息 4 小时。有什么我错过的吗?可能是时区问题?

【问题讨论】:

  • 您在 GMT-4 时区吗?

标签: iphone objective-c nsdate nsdateformatter


【解决方案1】:

简而言之,除非另有说明,否则将返回 GMT 日期。您可以设置时区以获取正确的日期。如果您打算使用应用程序中的日期来设置任何内容(例如 localNotification 时间或事件),您需要对日期做一些特别的事情,因为如果您在 iPhone 中设置日期,它将被设置为 GMT 时间并且会关闭几个小时。 (在您的情况下为 4 小时)。我做了我刚刚在我的一个应用程序中描述的事情。

我在不休息的情况下试图让它正常工作而弄得一团糟。这是一个巨大的 PITA,但它现在正在工作。我已复制、粘贴和编辑我的代码以供分享。再一次,它很乱,但它有效! pickerChanged 正在从 UIDatePicker 获取其信息

使用下面的代码。要回答您的问题,您可以在“destinationDate”处停止。这将为您返回当前时区的更正时间。我刚刚提供了额外的内容,以防您尝试在某处使用电话中的日期。

注意:举个简单的例子,我将事件提醒放在与日期选择器相同的功能中,你不会想要这样做,否则每次滚轮在日期选择器中滚动时都会设置很多提醒。强>

代码如下。

 - (void)pickerChanged:(id)sender
    {

        NSLog(@"value: %@",[sender date]);

        NSDate* date= [sender date]; 
        NSDateFormatter *formatter=[[[NSDateFormatter alloc]init]autorelease]; 
        [formatter setDateFormat:@"MM/dd/yyyy hh:mm:ss a"];
        [formatter setTimeZone:[NSTimeZone systemTimeZone]];

        [formatter setTimeStyle:NSDateFormatterLongStyle]; 

        NSString *dateSelected =[formatter stringFromDate:date]; 

        NSString *timeZone = [dateSelected substringFromIndex:12];



    NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];

    //here we have to get the time difference between GMT and the current users Date (its in seconds)
        NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:date];

    //need to reverse offset so its correct when we put it in the calendar
        correctedTimeForCalendarEvent = destinationGMTOffset + (2*(-1*destinationGMTOffset));

    //date to enter into calendar (we will use the correctedTimeForCalendarEvent to correct the time otherwise it will be off by a few hours )
       NSDate * destinationDate = [[[NSDate alloc] initWithTimeInterval:destinationGMTOffset sinceDate:date] autorelease];
        NSDate * dateForReminder = destinationDate;
        // return destinationDate;
        NSLog(@"value: %@ - %@",destinationDate,dateForReminder);

//DO NOT put this code in this same function this is for a quick example only on StackOverflow
//otherwise you will have reminders set everytime the users scrolled to a different time
    //set event reminder
    //make sure to import EventKit framework

        EKEventStore *eventDB = [[[EKEventStore alloc] init]autorelease];
        EKEvent *myEvent  = [EKEvent eventWithEventStore:eventDB];
        NSString * eventTitle = [NSString stringWithFormat:@"%@ - %@",app.dealerBusinessName,serviceOrComments.text];
        myEvent.title = eventTitle;

    //double check date one more time
        NSLog(@"value: %@",destinationDate);

    //set event time frame (1 hour) the "initWithTimeInterval" is where we account for the users timezone by adding the correctedTime from GMT to the calendar time ( so its not off by hours when entering into calendar)
        myEvent.startDate = [[[NSDate alloc] initWithTimeInterval:correctedTimeForCalendarEvent sinceDate:destinationDate ]autorelease];
        myEvent.endDate   = [[[NSDate alloc] initWithTimeInterval:3600 sinceDate:myEvent.startDate]autorelease];
        myEvent.allDay = NO;

    //set event reminders 1 day and 1 hour before
        myAlarmsArray = [[[NSMutableArray alloc] init] autorelease];
        EKAlarm *alarm1 = [EKAlarm alarmWithRelativeOffset:-3600]; // 1 Hour
        EKAlarm *alarm2 = [EKAlarm alarmWithRelativeOffset:-86400]; // 1 Day
        [myAlarmsArray addObject:alarm1];
        [myAlarmsArray addObject:alarm2];
        myEvent.alarms = myAlarmsArray;



        [myEvent setCalendar:[eventDB defaultCalendarForNewEvents]];

        NSError *err;

        [eventDB saveEvent:myEvent span:EKSpanThisEvent error:&err]; 

        if (err == noErr) {
            //no error, but do not show alert because we do that below.
        }

    }

【讨论】:

    【解决方案2】:

    NSDateFormatter 在创建 NSDate 对象时使用当前设备时区。 NSDate 以 GMT 格式存储日期/时间。因此,默认情况下 NSLog 将以 GMT+0 输出日期/时间。因此,您的代码没有任何问题。现在,如果您想将 NSDate 输出到当前时区,则必须使用 NSDateFormatter 对象。

    【讨论】:

      【解决方案3】:

      您的数据和日期格式化程序省略了 TimeZone 说明符。所以是这样的:

      [inputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZ"];
      

      可行 - Z 是时区说明符,将解析数字偏移量和时区代码。尽管在您的情况下,您的输入日期没有 TimeZone 信息,但它不起作用。

      您的正确时间字符串应类似于“2011-04-12 19:23:39 -0400”或“2011-04-12 19:23:39 EST”

      根据您从哪里获取日期,您应该修复它以生成完全合格的日期,如果您不能这样做,您将必须与服务器商定时区偏移量或简单地“硬编码”时区偏移量和将该秒数添加到您的 NSDate。

      【讨论】:

        【解决方案4】:

        日期被记录为 UTC 日期,最后的 +0000 可以看到。您用于解析字符串的日期格式假定您的本地时区可能比 UTC 晚 4 小时,夏令时和标准 -5 小时。

        【讨论】:

          【解决方案5】:

          使用-[NSDateFormatter setTimeZone:] 为日期格式化程序提供时区信息。您可以使用本地时区,或者如果您有与日期信息关联的固定时区,我建议使用名称(例如“America/East”)而不是缩写(例如“EST”或"EDT"),因为名称不会强制夏令时生效,而是使用该时区中该日期的正确夏令时偏移量。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-06-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多