开发者

iPhone - Strange problem with NSDate, NSString, and Timezones

开发者 https://www.devze.com 2023-03-16 06:26 出处:网络
I\'ve searched and haven\'t found an exact question like mine, so here goes nothing: I have a NSString containing a key that I pull from an XML feed. The key is a time in 24-hour format (e.g. 13:30 o

I've searched and haven't found an exact question like mine, so here goes nothing:

I have a NSString containing a key that I pull from an XML feed. The key is a time in 24-hour format (e.g. 13:30 or 15:00.) I'd like to convert the NSString to an NSDate and have it converted to the appropriate timezone based on the device's set timezone. The key is Unicode HH:mm (24:00), so I'm curious why this does not work as it should.

I've already gotten a basic outline th开发者_StackOverflowat should work, but alas does not. The 2nd NSLog (Got NS Date) returns null and the final log returns a strange number (1969-12--2147483629 -596:-31:-23 +0000 to be precise.) What am I doing wrong here?

Thanks in advance,

    NSString *dateString = [dict objectForKey:@"24hrdate"];
    NSLog(@"NSString Date: %@", dateString);

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];    
    [formatter setDateFormat:@"HH:mm"];
    NSDate *sourceDate = [formatter dateFromString:dateString]; 
    NSLog(@"Got NS Date: %@", sourceDate);

    NSTimeZone *sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    NSTimeZone *destinationTimeZone = [NSTimeZone systemTimeZone];

    NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
    NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
    NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;

    NSDate* destinationDate = [[[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate] autorelease];
    NSLog(@"Final Date: %@", destinationDate);


First of all understand that the date component will be 01-01-1970 because it isn't provided. I am assuming that you want the time to be 04:00 GMT if the input string is @"04:00". That you can achieve by setting the time zone of the formatter.

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];    
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
[formatter setDateFormat:@"HH:mm"];
NSDate *sourceDate = [formatter dateFromString:dateString]; 


NSDate is used to represent a date and time. While you can represent just a date by sticking with midnight, you can't really represent just a time of day with it. You can sort of fake this on the Mac (it defaults to some reasonable day), but on iOS you'll get wildly inaccurate times instead. (At least, you do on certain versions. This may have been fixed.)

There's two approaches here:

  1. You can build a NSDateComponents from your time of day and using dateByAddingComponents to add that to midnight on the date you want the time to appear on. This will fail to return the time you expect on a day where daylight savings begins or ends.

  2. You can build a date/time string using the date you want (NSDate) and the time (likely, as a NSString).

- (NSDate *)timeInHours: (NSInteger)hours
                minutes: (NSInteger)minutes
                seconds: (NSInteger)seconds
                 onDate: (NSDate *)inDate;
{
    id timeStr = [[NSMutableString alloc] initWithFormat: @"%02d:%02d:%02d", hours, minutes, seconds];
    id dateStr = [dateWithoutTimeFormatter stringFromDate: inDate];
    id dateTimeStr = [[NSString alloc] initWithFormat: @"%@ %@", dateStr, timeStr];
    [timeStr release];
    id dateTime = [dateWithTimeFormatter dateFromString: dateTimeStr];
    [dateTimeStr release];
    return dateTime;
}

If you really want just the time of day, just keep it around as a string.


Just wanted to post back that I did manage to achieve what I initially set out to do without any issues. Basically, I had to convert the string to NSDate, run that NSDate through a NSDateFormatter (set to the time's original timezone--NSDateFormatter's setTimeZone was helpful), pull an NSDate out of that, and then run that through another NSDateFormatter for the device's timezone. I then converted the resulting NSDate back to NSString, and stuck it on a UILabel.

This solution seems to have worked quite well, as I've set my devices to various timezones, and the timezone change is still correct.

EDIT: this was important to included, too:

NSString *date…….
date = [date stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
0

精彩评论

暂无评论...
验证码 换一张
取 消