Bug in dateByAddingTimeInterval - ios

After going almost crazy searching where my code failed ... I was able to isolated this strange behaviour. Look at what hapens when substracting -200 days
NSDate *now = [NSDate date]; //now is 2013-07-19
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"YYYY-MM-dd"];
NSDate *newDate1 = [now dateByAddingTimeInterval:60*60*24*-199];
newDateTmp=[format stringFromDate:newDate1];
NSLog(#"now:%# newDateTmp:%#",now,newDateTmp);
newDate1 = [now dateByAddingTimeInterval:60*60*24*-200];
newDateTmp=[format stringFromDate:newDate1];
NSLog(#"now:%# newDateTmp:%#",now,newDateTmp);
newDate1 = [now dateByAddingTimeInterval:60*60*24*-201];
newDateTmp=[format stringFromDate:newDate1];
NSLog(#"now:%# newDateTmp:%#",now,newDateTmp);
newDate1 = [now dateByAddingTimeInterval:60*60*24*-365];
newDateTmp=[format stringFromDate:newDate1];
NSLog(#"now:%# newDateTmp:%#",now,newDateTmp);
logs:
2013-07-19 15:58:46.123 Vendes[2927:907] now:2013-07-19 13:58:46 +0000 newDateTmp:2013-01-01 // This is OK
2013-07-19 15:58:46.124 Vendes[2927:907] now:2013-07-19 13:58:46 +0000 newDateTmp:2013-12-31 // This is INCORRECT!!!! Look at the YEAR
2013-07-19 15:58:46.125 Vendes[2927:907] now:2013-07-19 13:58:46 +0000 newDateTmp:2012-12-30 // This is OK
2013-07-19 15:58:46.127 Vendes[2927:907] now:2013-07-19 13:58:46 +0000 newDateTmp:2012-07-19 // This is OK
I guess it will hapopen also tomorrow substracting 201 .. ?? :)
Any idea?
Thks
PS. I solved it using
NSDate *newDate1= [NSDate dateWithTimeInterval:60*60*daysToAdd sinceDate:now];
that works for any daysToAdd value.

It is not a bug. The format you use is wrong. It should be
#"yyyy-MM-dd"
with lower-cased y
More information on upper-cased Y :
Y - Year (in "Week of Year" based calendars). This year designation
is used in ISO year-week calendar as defined by ISO 8601, but can be
used in non-Gregorian based calendar systems where week date
processing is desired. May not always be the same value as calendar
year.

Related

NSDateFormatter returning null value

I'm trying to format a date using NSDateFormatter however for some dates, formatted the same way, it returns the time without the first digit, and for others it returns null.
NSDateFormatter *dateFormat = [NSDateFormatter new];
[dateFormat setDateFormat:#"EEEE dd/MM/yyyy HH:mm"];
dateFormat.locale = [NSLocale localeWithLocaleIdentifier:#"en_AU"];
NSDate *startDate = [dateFormat dateFromString:startString];
NSDate *endDate = [dateFormat dateFromString:endString];
This date: "Saturday 1/21/2017 17:00" will return (null)
This date: "Thursday 2/9/2017 14:00" will return 2017-09-02 04:00:00 +0000
This date: "Thursday 2/9/2017 20:30" will return 2017-09-02 10:30:00 +0000
Can anyone shed some light on where I am going wrong.
Thanks
EEEE dd/MM/yyyy HH:mm to EEEE MM/dd/yyyy HH:mm. Just a small mistake inverting days and months place.
Because, clearly "Saturday 1/21/2017 17:00", means the 21th of January, because the 21th month in a year doesn't exist (at least, not here).
For the 10h difference, it's due to time zones. In en_AU (east coast I guess), there is a 10h difference from GMT.

Using NSDate to convert a string to a date, my dates are changed to 6 months back [duplicate]

This question already has an answer here:
NSDateFormatter dateFromString returns date with wrong month
(1 answer)
Closed 6 years ago.
I have an web service that spits out some dates, and in my iOS app, I'm converting UTC date to local date. I have verified that the web service is spitting out UTC dates and that iOS recognizes it as UTC.
Once i have converted my web service JSON to an NSMutableArray, set a break point and type po [listOfTasks valueForKey:#"LASTEMAILDATE"]
Results
<__NSArrayI 0x157068c80>(
,
7/28/2016 2:01:41 PM,
7/28/2016 2:01:39 PM,
7/28/2016 2:01:42 PM
)
Now, i do a for loop
for (int i = 0; i < listOfTasks.count; i++) {
FireStormCategories *cat = [listOfTasks objectAtIndex:i];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"mm/dd/yyyy hh:mm:ss a"];
NSDate *date = [df dateFromString:cat.LASTEMAILDATE];
MNLog(#"%# was changed to %#", cat.LASTEMAILDATE, [df stringFromDate:date]);
}
that log spits out
was changed to (null)
7/28/2016 2:01:41 PM was changed to 01/28/2016 02:01:41 PM (expecting: 7/28/2016 10:01:41 AM )
7/28/2016 2:01:39 PM was changed to 01/28/2016 02:01:39 PM (expecting: 7/28/2016 10:01:39 AM )
7/28/2016 2:01:42 PM was changed to 01/28/2016 02:01:42 PM (expecting: 7/28/2016 10:01:42 AM )
my first object has no date, the (null) is expected, however, this is where I'm confused. my other 3 dates are changed to a date that reflects 6 months ago and the hours should go back 5 (EST).
You are using wrong format for month. MM is used for month and mm is used for minutes
[df setDateFormat:#"mm/dd/yyyy hh:mm:ss a"];
should be
[df setDateFormat:#"MM/dd/yyyy hh:mm:ss a"];
The 01 you are getting is the minutes from the date.

how to convert date according to time zones

So in my project a user from USA set some time say it was 10:30 am
and now when a person some another country see that time then it should be according to their timezone .
For Example in USA it is 5:30 am now
and in india it is 6:30 pm , so if after 5 hours a person in india sees that then that person should see 6:30 pm for that post
Use php function gmdate()
string gmdate(string $format[,int $timestamp= time()] )
Identical to the date()function except that the time returned is Greenwich Mean Time (GMT).
Parameters format The format of the outputted date string. See the formatting options for the date() function. timestamp The optional timestamp parameter is an integer Unix timestamp that defaults to the current local time if a timestamp is not given. In other words, it defaults to the value of time().Return Values Returns a formatted date string. If a non-numeric value is used for timestamp, FALSE is returned and an E_WARNING level error is emitted.
in timestamp add the interval to.
Ex if GMT zone is 5 say then add timestamp+5*60*60
Use below function:
class func getDateWithFormat(format: String) -> NSDate {
var dateFormatter: NSDateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone.localTimeZone()
dateFormatter.dateFormat = format
var newDate: NSDate = dateFormatter.dateFromString(dateFormatter.stringFromDate(NSDate()))
return newDate
}
Eg: var todaysDate: NSDate = NSDate.getDateWithFormat("dd:mm:yyyy hh:mm:ss a")
I created the below function to solve this problem.
How it works: suppose this was your local time converted to GMT zero - 2016-04-14 21:00:00 +0000
and when I convert it using following function, I'm here in New Delhi India, which has GMT+05:30, then I will get time 2:30 of morning.
+(NSString*)getLocalTimeFromGMTzero : (NSString*)GMTzerioTimeString {
NSDateFormatter *df = [NSDateFormatter new];
[df setDateFormat:#"yyyy-MM-dd HH:mm"];
//Create the date assuming the given string is in GMT
df.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
NSDate *date = [df dateFromString:GMTzerioTimeString];
//Create a date string in the local timezone
df.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:[NSTimeZone localTimeZone].secondsFromGMT];
NSString *localDateString = [df stringFromDate:date];
NSLog(#"date = %#", localDateString);
return localDateString;
}

Issues in converting date string (any time zone) to NSDate of French Time Zone

I want to convert a date string (can be in any time zone) to a date in French Time Zone. I am using following code.
NSString * dateString = #"27/05/2015 - 19:00" // system time zone is GMT +5
NSDateFormatter* frenchDateFormatter = [[NSDateFormatter alloc] init];
[frenchDateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"Europe/Paris"]];
[frenchDateFormatter setDateFormat:#"dd/MM/yyyy - HH:mm"];
NSDate *frenchDate = [frenchDateFormatter dateFromString:dateString];
NSLog(#"%#",frenchDate);
NSString * frenchString = [frenchDateFormatter stringFromDate:frenchDate];`
Elaboration
--> System time zone is GMT +5
--> French time zone is GMT +2
Date string = 27/05/2015 - 19:00
Expected result = 27/05/2015 - 16:00
Actual result (NSDate) = 2015-05-27 17:00:00 +0000
Actual result (NSString from date) = 27/05/2015 - 19:00
Kindly point out if I am missing something
If you use NSLog to display dates it'll be displayed in UTC. So either you have to convert in your head, or don't use it. I wrote a long answer explaining this to a different question.
Because you have set the timezone of your parsing dateFormatter to Paris the string you parse is treated as "time in paris". That's your problem, you actually wanted to parse it in local time.
The results you get are exactly as one would expect.
You create a NSDate that relates to "19:00 in Paris". Since Paris is UTC+2 that date is 17:00 in UTC (or in +0000). If you convert that date back to "time in Paris" you end up with the same string as before.
If you want to convert the representation of a point in time in your location to a different representation at a different location you have to use two dateFormatters.
NSString *localDateString = #"27/05/2015 - 19:00" // system time zone is GMT +5
NSDateFormatter* localDateFormatter = [[NSDateFormatter alloc] init];
[localDateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[localDateFormatter setDateFormat:#"dd/MM/yyyy - HH:mm"];
NSDate *date = [localDateFormatter dateFromString:localDateString]; // date contains point in time. It no longer has a timezone
NSDateFormatter* franceDateFormatter = [[NSDateFormatter alloc] init];
[franceDateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"Europe/Paris"]];
[franceDateFormatter setDateFormat:#"dd/MM/yyyy - HH:mm"];
NSString * timeInFranceString = [franceDateFormatter stringFromDate:date]; // representation of the point in time from above for people in Paris
This line prints out the date/time in GMT, as it calls [NSDate description], and there is a potential difference between systemTimeZone and GMT, hence the difference you are seeing:
NSLog(#"%#",currentDate);
If you want to see what the date/time is for a particular timezone then use the NSDateFormatter object to get the string.
A date doesn't have a time zone information. A date is internally represented as a number. We don't have to know anything about that number (it's a number of seconds from a fixed date in UTC), the important thing is to understand that to display a date to a user, you have to convert it to a string first.
A string representation of a number is generated from a date using a date format and a time zone. For all date -> string and string -> date conversions you can use NSDateFormatter.
You have successfully parsed currentDate from your string representation. If you want to reverse the process and get the string representation, just use [currentDateFormatter stringFromDate:currentDate]
Check at http://www.timeanddate.com/worldclock/
Right now Paris is two hours ahead of UTC. The result is absolutely correct. NSDate keeps dates in UTC. The idea is that if any two people look at their watch at the same moment, and convert the time they see on their watch to NSDate, they will get the same result.
You cannot get an NSDate for a timezone. NSDate doesn't support time zones. The only way to get a date with a time zone is to use NSDateFormatter to convert it to a string.

Validation of date and month

i have a current date using NSDate which is ma start date....and i add 4 more days to the current date where i get ma endDate..
NSString *StrtDate= [dateFormatter stringFromDate:[NSDate date]];
int daysToAdd = 4;
NSDate *newDate1 = [[NSDate date] dateByAddingTimeInterval:60*60*24*daysToAdd];
NSString *StopDate= [dateFormatter stringFromDate:newDate1];
suppose the current date is todays date..thats 28th of jan the end date becomes 32nd of Jan which is invalid rite?
how do u validate the date??
Have you run the code and checked whether the resultant date is indeed 32nd January?
The framework is intelligent enough to understand valid dates. You will get correct date.
You don't need to worry about this as the date framework knows how many days are in each month.

Resources