Objective C: Incorrect Output while using NSDates - objective-c

I am trying to get the start and end dates of the current month. There are a few similar questions here, but I am getting unexpected results while using them. Here's what I did:
NSDate *monthStart,*monthEnd;
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [cal components:NSDayCalendarUnit fromDate:[NSDate date]];
[comps setDay:1];
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
monthStart = [cal dateFromComponents:comps];
[comps setDay:[[NSCalendar currentCalendar]
rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:[NSDate date]].length];
[comps setHour:23];
[comps setMinute:59];
[comps setSecond:59];
monthEnd = [cal dateFromComponents:comps];
NSLog(#"%#",monthStart);
NSLog(#"%#",monthEnd);
Unfortunately the output is :
2012-12-24 15:39:28.159 Popup[1010:403] 0001-12-31 18:06:32 +0000
2012-12-24 15:39:28.160 Popup[1010:403] 0001-01-31 18:06:31 +0000
BTW, the timezone configured in my machine is +5:30

I have modified your code little, to get the correct answer
NSDate *monthStart,*monthEnd;
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *currentDate = [NSDate date];
NSDateComponents *comps = [cal components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:currentDate];
[comps setDay:1];
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
[cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:19800]];
monthStart = [cal dateFromComponents:comps];
[comps setDay:[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length];
[comps setHour:23];
[comps setMinute:59];
[comps setSecond:59];
monthEnd = [cal dateFromComponents:comps];
NSLog(#"Start %#",monthStart);
NSLog(#"End %#",monthEnd);

If you want to know the starting and ending date for current month...
Starting is always 1st, and ending can be calculated by month name!!!
Then it is very simple date arithmetic,
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
NSMutableArray *months=[NSMutableArray arrayWithObjects:#"Jan",#"Feb",#"Mar",#"Apr",#"May",#"Jun",#"Jul",#"Aug",#"Sep",#"Oct",#"Nov",#"Dec", nil];
NSMutableArray *days=[NSMutableArray arrayWithObjects:#"31",#"28",#"31",#"30",#"31",#"30",#"31",#"31",#"30",#"31",#"30",#"31", nil];
//check if leap
[dateFormat setDateFormat:#"YYYY"];
NSInteger year=[[dateFormat stringFromDate:[NSDate date]]integerValue];
if(((year%4==0)&&(year%100!=0))||(year%400==0)) {
[days replaceObjectAtIndex:1 withObject:#"29"];
}
NSMutableDictionary *daysInMonthDict=[[NSMutableDictionary alloc]initWithObjects:days forKeys:months];
[dateFormat setDateFormat:#"MMM"];
NSLog(#"Starting date is 1 and ending date is %#",[daysInMonthDict objectForKey:[dateFormat stringFromDate:[NSDate date]]]);

Related

Check if two dates are one month apart

I'm trying to check if two dates are 1 month apart. I read that I should use this method components:fromDate:toDate:options: from NSCalendar
My code
#define FORMAT_DATE_TIME #"dd-MM-yyyy HH:mm"
NSDate *updateDate = [Utils getDateFromString:airport.updateOn withFormat:FORMAT_DATE_TIME];
NSDate *now = [NSDate date];
NSString *nowString = [Utils getStringFromDate:now withFormat:FORMAT_DATE_TIME];
now = [Utils getDateFromString:nowString withFormat:FORMAT_DATE_TIME];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comps = [calendar components:NSCalendarUnitMonth fromDate:updateDate toDate:now options:0];
NSLog(#"%ld", (long)[comps year]);
NSLog(#"%ld", (long)[comps month]);
NSLog(#"%ld", (long)[comps day]);
These are the logs:
(lldb) Year: 9223372036854775807
(lldb) Month: 0
(lldb) Day: 9223372036854775807
(lldb) po now 2017-08-23 11:54:00 +0000
(lldb) po updateDate 2017-08-23 11:48:00 +0000
Shouldn't all the value be zero?
The below line does not include the Year (NSCalendarUnitYear) and Day (NSCalendarUnitDay) component, only Month (NSCalendarUnitMonth) component is included.
NSDateComponents *components = [calendar components:NSCalendarUnitMonth fromDate:updateDate toDate:now options:0];
Add NSCalendarUnitYear and NSCalendarUnitDay to get [comps year] & [comps day] as 0.
Like this :
NSDateComponents * components = [calendar components:NSCalendarUnitMonth |NSCalendarUnitYear|NSCalendarUnitDay fromDate:updateDate toDate:now options:0];
you can use this
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:FORMAT_DATE_TIME];
NSDate *updateDate = [dateFormatter dateFromString:#"24-07-1990 15:20"];
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *comps = [calendar components:unitFlags fromDate:updateDate toDate:now options:0];
NSLog(#"%ld", (long)[comps year]);
NSLog(#"%ld", (long)[comps month]);
NSLog(#"%ld", (long)[comps day]);

NSDate conversion setting weekday

I have an NSDate object *myDate.I can get the week day from this date and I want to set the weekday to an integer c and get the new date object in that week only.
I searched for it and I found the answer,here is the code..
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:1];
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:comps toDate:[NSDate date] options:0];
NSLog(#"new date==%#",newDate);
This will return date of the next day.
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"MMM dd, yyy"];
date = [formatter dateFromString:string];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger units = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit;
NSDateComponents *components = [calendar components:units fromDate:date];
NSInteger day = [components day];
NSInteger weekday = [components weekday]; // if necessary

NSCalendar and NSDateComponents returning unexpected date

I'm trying to create an NSDate from NSCalendar and NSDateComponents with:
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone localTimeZone]];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:[self.day intValue]];
[components setMonth:[self.month intValue]];
[components setYear:[self.year intValue]];
self.date = [calendar dateFromComponents:components];
When the day, month, year are : 9/31/2011 the NSDate is for 10/1/2011. I set the timezone for the NSCalendar after testing which didn't change the NSDate. I also tried
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
Which gave me back 9/30/2011. Anyone see an error in the way I'm calculating this?
Thanks.
Well, september 31 is really october first.
But a component has to know in which calendar to work. The following code is from apple
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:6];
[comps setMonth:5];
[comps setYear:2004];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];

Building NSDate from integers (year ... second) with Cocoa/objective-C

I have year, mont, ... , second in integer type, and I need to build NSDate from them.
I tried this code, but I got (null).
NSDateFormatter *tempFormatter = [[[NSDateFormatter alloc]init]autorelease];
[tempFormatter setDateFormat:#"yyyy-mm-dd hh:mm:ss"];
NSString* message = [NSString stringWithFormat:#"%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second];
NSDate *day3 = [tempFormatter dateFromString:message];
What's wrong with this code?
It would be more straightforward to create an NSDateComponents with your date components, and then use NSCalendar's dateFromComponents: to convert it to a date. The documentation for NSDateComponents has an example of how to do exactly this:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:day];
[comps setMonth:month];
[comps setYear:year];
[comps setHour:hour];
[comps setMinute:minute];
[comps setSecond:second];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [cal dateFromComponents:comps];
[comps release];
instead of
[tempFormatter setDateFormat:#"yyyy-mm-dd hh:mm:ss"];
write
[tempFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];

get NSDate from the day of the year

I have a the day of the year for example 346.
I want to get NSDate to now what month and day it means.
Your steps here:
Instantiate calendar
Build a date with 1st Jan. of the year
Add the number of days - 1 and build a date with that
Get the components you are interested in
Watch out if the date you get is 0- or 1-based.
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setYear:theYear];
[comps setMonth:1];
[comps setDay:1];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
NSDateComponents *compsToAdd = [[NSDateComponents alloc] init];
[comps setDay:theDay-1];
NSDate *finalDate = [gregorian dateByAddingComponents:compsToAdd date options:0];
[compsToAdd release]
NSDateComponents *interestingComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit) fromDate:finalDate];
NSInteger day = [interestingComponents day];
NSInteger month = [interestingComponents month];
[gregorian release];
See the -dateByAddingComponents:toDate:options: method of NSCalendar.