issue with NSDate I am removing year but takes 0001 as year - ios

Below is my code, and I will explain things in it
NSDateFormatter *formater = [[NSDateFormatter alloc] init] ;
[formater setDateFormat:#"MM-dd"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger desiredComponents = (NSDayCalendarUnit | NSMonthCalendarUnit);
NSDateComponents *firstComponents = [calendar
components:desiredComponents fromDate:fDate];
NSDateComponents *secondComponents = [calendar
components:desiredComponents fromDate:eDate];
NSDateComponents *thirdComponents = [calendar
components:desiredComponents fromDate:mdate];
NSDate *from = [calendar dateFromComponents:firstComponents];
NSDate *end = [calendar dateFromComponents:secondComponents];
NSDate *middle = [calendar dateFromComponents:thirdComponents];
NSString * froms = [formater stringFromDate:from];
NSLog(#"sringfroms:%#",froms);
NSLog(#"datefrom:%#",from);
NSString * ends = [formater stringFromDate:from];
NSLog(#"sringends:%#",ends);
NSLog(#"dateend:%#",end);
NSString * middles = [formater stringFromDate:from];
NSLog(#"sringmiddles:%#",middles);
NSLog(#"datemiddle:%#",middle);
And this is what gets printed.
sringfroms:06-30
datefrom:0001-06-29 18:06:32 +0000
sringends:06-30
dateend:0001-08-02 18:06:32 +0000
sringmiddles:06-30
datemiddle:0001-07-14 18:06:32 +0000
You can see that i am removing year from date which get printed in string but when i make date it takes 0001 automatically. I am using kal calendar and i want to mark for month and day only so it should get marked for every year
if (([middle compare:from] == NSOrderedDescending)
&&([middle compare:end] == NSOrderedAscending)) {
[holidays addObject:[Holiday holidayNamed:naMMe
birthDate:bDate iDs:aIDDS date:middle]];
}
Any help will be highly appreciated

Its OKAY, since you are not using NSYearCalendarUnit in your following code
NSInteger desiredComponents = (NSDayCalendarUnit | NSMonthCalendarUnit);
so NSDate is assuming 0001 as default year, if you add NSYearCalendarUnit in the above code it will give correct year, like below
NSInteger desiredComponents = (NSDayCalendarUnit
| NSMonthCalendarUnit | NSYearCalendarUnit);

Well,if you are not mensioned any component then it'l take always
first value(01,0001 etc) that is default nature of NSCalendar,for resolving your
problem you need to convert that date to your date formatt.

Related

How to find Next Sunday in different Timezone (EST & IST)

I have to find next Sunday date (NSDate) from device's current date.
I have used below logic:
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar components:NSCalendarUnitWeekday | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
NSUInteger weekdayToday = [components weekday];
NSInteger daysToMonday = (8 - weekdayToday) % 7;
NSDate *weekEndPrev = [self dateByAddingTimeInterval:60*60*24*daysToMonday];
Here, in EST if time is near to 11 PM, I'm getting Monday as Weekend.
Let me know feasible solution. I have tried many options. Nothings works with 2 different timezones.
Thanks in Advance.
You need just to get the number of days you need and then just add them to your current date:
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate * newDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:value toDate:date options:0];
where value - is the number of days to add
Find current week Sunday Date first then add 7 days using NSDateComponents.
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *weekdayComponents = [gregorian components:NSCalendarUnitWeekday fromDate:today];
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
[componentsToSubtract setDay:(0 - ([weekdayComponents weekday] - 1))];
NSDate *sudayCurWeek = [gregorian dateByAddingComponents:componentsToSubtract toDate:today options:0];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:7];
NSDate *nextSunday = [gregorian dateByAddingComponents:offsetComponents toDate:sudayCurWeek options:0];
NSLog(#"%#",nextSunday);
You can do this without any math, which is best left to NSCalendar as it handles daylight savings etc. First you need a calendar with the correct time zone. For example for IST:
NSCalendar *gc = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
gc.timeZone = [NSTimeZone timeZoneWithName:#"IST"];
Then you can use nextDateAfterDate:matchingUnit:value:options: to find the start of the next Sunday after a given time. For example:
NSDate *start = ... // the time you wish to start from
NSDate *nextSunday =
[gc nextDateAfterDate:start
matching:UnitNSCalendarUnitWeekday // match based on weekday number
value:1 // Sunday = weekday 1
options:NSCalendarMatchNextTime // read the docs!
];
The returned date, nextSunday, will be the next Sunday at 00:00 in the timezone of the calendar, gc.
HTH
Finally, I got solution..
NSDateComponents *components = [[NSCalendar currentCalendar] componentsInTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"] fromDate:[NSDate date]]; // Pass date for which you want to find next Sunday
NSUInteger weekdayToday = [components weekday];
NSInteger daysToMonday = (8 - weekdayToday) % 7;
NSDate *weekEndPrev = [[NSDate date] dateByAddingTimeInterval:60*60*24*daysToMonday];

NSDateComponents issue - set incorrect day [duplicate]

This question already has answers here:
Unexpected value from NSDate
(2 answers)
Closed 6 years ago.
There are many issues similar to mine, but something goes wrong. Why function setDay sets to 1 day less? Where did I go wrong?
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *today = [NSDate date];
NSLog(#"today date = %#", today);
NSDateComponents *components = [calendar components:(NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear ) fromDate:today];
[components setDay:1];
NSLog(#"modified date = %#", [calendar dateFromComponents:components]);
Log:
today date = 2016-07-04 10:01:30 +0000
modified date = 2016-06-30 21:00:00 +0000
Modified date should be 2016-07-01
Likely it is 2016-07-01, 24:00 GMT. NSLog() prints it out for GMT, not your locale time.
See here: Unexpected value from NSDate
You should add NSCalendarUnitHour in NSDateComponents like this then then you get correct date
NSDateComponents *components = [calendar components:(NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear |NSCalendarUnitHour) fromDate:today];
Try this code:
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setTimeZone:[NSTimeZone defaultTimeZone]]; // your time 00:00:00
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSLog(#"modified date = %#", [df stringFromDate:[calendar dateFromComponents:components]]); // Date format NSString

Why [calendar dateFromComponents:] always return hour 16 ?

When I pass the [NSDate date] to NSDateComponents , then pass back after the weekday modified, I always got the hour 16:00:00 . Why ?
Code belows:
{
NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *now = [NSDate date];
NSLog(#"now = %#",now);
NSDateComponents *firstDayOfWeek = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday fromDate:now];
firstDayOfWeek.weekday = 1; // Monday as first day of week
NSDate *firstDayOfWeekDate = [calendar dateFromComponents:firstDayOfWeek];
NSLog(#"first day = %#", firstDayOfWeekDate);
}
{
NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *now = [NSDate date];
NSLog(#"now = %#",now);
NSDateComponents *firstDayOfWeek = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:now];
firstDayOfWeek.weekday = 1; // Monday as first day of week
firstDayOfWeek.hour = 1;
firstDayOfWeek.minute = 1;
firstDayOfWeek.second = 1;
NSDate *firstDayOfWeekDate = [calendar dateFromComponents:firstDayOfWeek];
NSLog(#"first day = %#", firstDayOfWeekDate);
}
And the output is :
now = 2016-01-18 03:14:08 +0000
first day = 2016-01-17 16:00:00 +0000
now = 2016-01-18 03:14:08 +0000
first day = 2016-01-17 17:01:01 +0000
Why the hour begins with 16 ?
NSDateComponents isn't making it 16:00:00. It's making it midnight in your current timezone. But the NSLog is showing you the equivalent GMT time. That's what the +0000 means: e.g. GMT +00:00.
Bottom line, if you want to see the resulting NSDate object in your local time zone, you should use NSDateFormatter.
This is due to timezone.
Try to add NSDateFormatter before you output the date with NSLog, e.g.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
[dateFormatter setTimeStyle:NSDateFormatterLongStyle];
NSString *dateDisplay = [dateFormatter stringFromDate:firstDayOfWeekDate];
NSLog(#"first day = %#",dateDisplay);
You can refer this article for more examples.

Date Formatting is Weird

I have a date string that looks like this:
1391640679661
When I use this code:
NSString *seconds = #"1391640679661";
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[seconds doubleValue]];
I end up with this:
46069-05-03 07:27:41 +0000
So what's happening here? Is this a particular date format that I'm not accounting for? Or am I doing something else wrong?
Apple's own api will do all the hard work for you to format components as per your need.
If you want to get individual components as well you can apply below approach.
NSTimeInterval theTimeInterval = 1391640679661;
// Get the system calendar
NSCalendar *sysCalendar = [NSCalendar currentCalendar];
// Create the NSDates
NSDate *date1 = [[NSDate alloc] init];
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:theTimeInterval sinceDate:date1];
// Get conversion to months, days, hours, minutes
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *conversionInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0];
NSLog(#"Conversion: %dmin %dhours %ddays %dmoths",[conversionInfo minute], [conversionInfo hour], [conversionInfo day], [conversionInfo month]);
To convert a timestamp string into NSDate, you need to divid the timestamp double value to 1000, and then call dateWithTimeIntervalSince1970:
NSString *timestamp = #"1391640679661";
double seconds = [timestamp doubleValue]/1000.0;
NSDate *date = [NSDate dateWithTimeIntervalSince1970:seconds];
The result is:
2014-02-05 22:51:19 +0000

UITableview title bar with date for week?

How can I have the title of UITableview with date?
I know I can edit the title using:
self.title=#"meals for ..";
I want to add the date for one week. How can I do that?
You can get a date like this:
NSDate *theDateToday = [NSDate date];
And format it like this:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEE MMM dd"];
NSString *theDateAsAString = [dateFormatter stringFromDate:theDateToday];
Combine that with what you have like this:
self.title = [NSString stringWithFormat:#"meals for %#", theDateAsAString];
As for finding the days of the week, you could try adapting this answer.
- (NSString *)getWeekStartDateAsString:(NSDate *)date {
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];
int dayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:today] weekday];// this will give you current day of week
[components setDay:([components day] - ((dayofweek) - 2))];// for beginning of the week.
NSDate *beginningOfWeek = [gregorian dateFromComponents:components];
NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init];
[dateFormat_first setDateFormat:#"yyyy-MM-dd"];
dateString2Prev = [dateFormat stringFromDate:beginningOfWeek];
weekstartPrev = [[dateFormat_first dateFromString:dateString2Prev] retain];
return weekstartPrev;
}
- (NSString *)getWeekEndDateAsString:(NSDate *)date {
NSCalendar *gregorianEnd = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsEnd = [gregorianEnd components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];
int Enddayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:today] weekday];// this will give you current day of week
[componentsEnd setDay:([componentsEnd day]+(7-Enddayofweek)+1)];// for end day of the week
NSDate *EndOfWeek = [gregorianEnd dateFromComponents:componentsEnd];
NSDateFormatter *dateFormat_End = [[NSDateFormatter alloc] init];
[dateFormat_End setDateFormat:#"yyyy-MM-dd"];
dateEndPrev = [dateFormat stringFromDate:EndOfWeek];
weekEndPrev = [[dateFormat_End dateFromString:dateEndPrev] retain];
return weekEndPrev;
}
You end result might look like this:
self.title = [NSString stringWithFormat:#"meals for %#-%#", [self getWeekStartDateAsString:theDateToday], [self getWeekEndDateAsString:theDateToday]];
A rarely known NSCalendar method will be the best option IMO
rangeOfUnit:startDate:interval:forDate:. It gives you the start and the duration (interval) for a certain time unit. With it it is easy to find the start of the week in the used calendar and add the range-1 to get the latest second in that week.
With the also rarely seen localizedStringFromDate:dateStyle:timeStyle: Available in OS X v10.6, iOS 4.0 it is easy to create a localized representation of the dates.
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDate *startOfTheWeek;
NSDate *endOfWeek;
NSTimeInterval interval;
[cal rangeOfUnit:NSWeekCalendarUnit
startDate:&startOfTheWeek
interval:&interval
forDate:now];
//startOfWeek is 2013-06-02 22:00:00 +0000 now (note: it is GMT with timezone support for my timezone Europe/Berlin/DST)
endOfWeek = [startOfTheWeek dateByAddingTimeInterval:interval-1];
// 2013-06-09 21:59:59 +0000
NSString *text = [NSDateFormatter localizedStringFromDate:startOfTheWeek
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterNoStyle];
text = [text stringByAppendingString:#" to "];
text = [text stringByAppendingFormat:#"%#", [NSDateFormatter localizedStringFromDate:endOfWeek
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterNoStyle]];
self.title=text;
results in 03.06.13 to 09.06.13 for my german locale, where Monday is start of the week.

Resources