首页 文章

NSDate格式输出错误的日期

提问于
浏览
8

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

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

NSDate *date = [inputFormatter dateFromString:newDateString];

但是当我记录日期时它输出的是:

2011-04-12 23:23:39 0000

大约需要4个小时 . 我错过了什么吗?可能是时区问题?

5 回答

  • 1

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

  • 2

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

    我弄得一团糟,试图让这个工作正常,而不用关闭时间 . 这是一个巨大的PITA,但现在正在努力 . 我复制,粘贴和编辑了我的代码以进行分享 . 再次,它凌乱但它的作品! pickerChanged从UIDatePicker获取其信息

    Using the code below. To answer your question, you can stop at "destinationDate". That will return to you the corrected time for your current time zone. I just provided the extra incase you were trying to use the date in the Phone somewhere.

    NOTE: for a quick example i put the Event reminder in the same function as the datepicker, you will NOT want to do that otherwise you will have alot of reminders set everytime the wheel scrolls in the datepicker.

    代码如下 .

    - (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.
            }
    
        }
    
  • 5

    您的数据和日期格式化程序省略了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几秒钟 .

  • 1

    记录日期,因为UTC日期最后可以通过 +0000 查看 . 您用来解析字符串的日期格式假设您的本地时区可能比UTC夏令时低4小时,标准为-5小时 .

  • 1

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

相关问题