NSString to NSDate and back again to NSString

50 views Asked by At

I have a date string in this format: 2022-09-07T11:11:16+0300 and I want to convert it to NSDate and back again to NSString, I use this code:

NSString * dateCreatedString = @"2022-09-07T11:11:16+0300";
self.dateFormat = [[NSDateFormatter alloc] init];
[self.dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
NSDate * date = [self.dateFormat dateFromString:dateCreatedString];

.
.
.

NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
formatter2.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSSZ";
NSString * newStr = [formatter2 stringFromDate:date];

And i get this string date: 2022-09-07 04:11:16.000-0400 instead of: 2022-09-07 11:11:16.000+0300.

Any idea what can be the problem?

1

There are 1 answers

0
The Dreams Wind On BEST ANSWER

Just specify the timeZone for your formatter (by default it refers to the system time zone when forming a string out of an NSDate):

NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
formatter2.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSSZ";
formatter2.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:60 * 60 * 3];
NSString *newStr = [formatter2 stringFromDate:date];

EDIT

If you want to preserve original time zone of the date string, i'm not aware of a simple way of doing so. You will have to parse the string manually and extract this information somehow. Here is how I would implement such a functions:

NSTimeZone *_Nullable NSTimeZoneFromDateString(NSString *_Nonnull dateString, NSError *__autoreleasing _Nullable *_Nullable error) {
    static NSDateFormatter *formatter;
    static dispatch_once_t predicate;
    
    dispatch_once(&predicate, ^{
        formatter = [NSDateFormatter new];
        formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSSZ";
    });
    
    // Checks whether the dateString is compatible with date format
    if ([formatter getObjectValue:nil forString:dateString range:nil error:error]) {
        return nil;
    }

    NSString *timeZoneString = [dateString substringFromIndex:dateString.length - 5];
    unichar signString = [timeZoneString characterAtIndex:0];
    NSInteger hours = [timeZoneString substringWithRange:NSMakeRange(1, 2)].integerValue;
    NSInteger minutes = [timeZoneString substringWithRange:NSMakeRange(3, 2)].integerValue;
    NSInteger deltaSeconds = 60 * minutes + 60 * 60 * hours;
    NSInteger secondsFromGMT = signString == '+' ? deltaSeconds : -deltaSeconds;
    return [NSTimeZone timeZoneForSecondsFromGMT:secondsFromGMT];
}

In the client code:

formatter2.timeZone = NSTimeZoneFromDateString(dateCreatedString, nil);