Get the upcoming month from NSArray - ios

I have an Array with some month and year.for ex array {Jan 2015,feb 2015, june 2015, september 2015}. I want to get the index of the current month and am getting it. If there is no current month, then i want to get the upcoming recent month.In the above example i want to get the index of september 2015.
Help much appreciated.
Below is the code to get the index of the current month.
if ([titleMonth isEqualToString:currentMonth])
{
indexNumber=[[self.dataByMonth valueForKey:#"title"]indexOfObject:currentMonth];
}
Here am getting the current month from NSDate.

Create NSDataComponents
First, you need to fill the array with NSDateComponents objects. Look at this method in particular.
For example. To create NSDateComponents for current month.
NSDateComponents *dateComponents = [[NSCalendar currentCalendar]components:(NSCalendarUnitMonth | NSCalendarUnitYear) fromDate:[NSDate date]];
Then fill up your array with these components.
Loop through the array until the current month and year is equal or lesser than the looping month and year. If they are equal, you have your current month. If its lesser, the item in the array is the next month/year.
Would this work?
Here is a rough sample code
for(NSDateComponents *components in arrayOfMonths)
{
if(currentMonth.date == components.date)
NSLog(#"current month is on the list");
else if(currentMonth.date < components.date)
{
NSLog(#"this is the next month on the list");
break;
}
}

if your first array is {Jan 2015,feb 2015, May 2015, september 2015}. Keep another array with all the months {Jan 2015,feb 2015,Mar 2015,..... Dec 2015}.
If current month is June and it is not there in 1st array. Take the next element in 2nd array and check with the 1st array. So, check July is there in 1st array and continue this process until you find match. So, you will get September 2015.
Don't know if this is what you wanted.

Related

Why does ordinalityOfUnit use Monday as the first day of the week when using NSCalendarUnitEra?

I'm trying to calculate the number of calendar weeks between two dates. I'm using the following code:
[cal ordinalityOfUnit:NSCalendarUnitWeekOfYear inUnit:NSCalendarUnitEra forDate:thenDate];
[cal ordinalityOfUnit:NSCalendarUnitWeekOfYear inUnit:NSCalendarUnitEra forDate:nowDate];
A date of 15-1-2017, a Sunday, results in 105192 weeks, and 16-1-2017, a Monday, results in 105193. That would indicate it is using Monday as the first day of the week. I have verified that cal.firstWeekday is 1. If I change the inUnit from NSCalendarUnitEra to NSCalendarUnitYear it works correctly. Is there a way around this?
I suppose I could subtract one day from both dates but that seems very hackie.
After much experimenting, if you make sure all dates are in GMT and you set cal timeZone to GMT it works as one would expect.

How to get start and end dat for week number in objective c

In my iOS app, I have a week number and I need to get the start and end date for that week number.
I'm building an app with which the manager of a company can keep track of the worked hours of staff. These worked hours are processed per day in a custom Registration object.
In this object, the date, begin time, end time and break time are stored and based on those values, the worked hours are calculated.
Then, all Registration objects are stored in a WorkWeek object, containing a week number and an array of registrations. WorkWeek's are constructed based on weeknumbers and run from monday through sunday. In this WorkWeek object, the total worked hours, extra hours and wage are calculated.
Now obviously, I can't reliably calculate extra hours if a Workweek is not a full week that runs from monday through friday. This particularly occurs when the user chooses to get all registrations from a mont from my database. A month does not start on monday and does not end on sunday exactly four weeks later, so i'm dealing with unreliable week object.
Wrapping up
To make sure the information I display in my app is reliable, I need to determine whether a certain week (like week 1 or week 52) contains at least 7 days and, if not, I need to set a bool to FALSE which then triggers a notification to my user.
How can I get the begin and end date of a week based on a weeknumer?
This shows how it could be done:
NSCalendar *cal = [NSCalendar currentCalendar];
// Start of week:
NSDateComponents *comp = [[NSDateComponents alloc] init];
comp.weekday = cal.firstWeekday;
comp.weekOfYear = 1; // <-- fill in your week number here
comp.year = 2015; // <-- fill in your year here
NSDate *startOfWeek = [cal dateFromComponents:comp];
// Add 6 days:
NSDate *endOfWeek = [cal dateByAddingUnit:NSCalendarUnitDay value:6 toDate:startOfWeek options:0];
// Show results:
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateStyle = NSDateFormatterShortStyle;
NSLog(#"%#", [fmt stringFromDate:startOfWeek]);
NSLog(#"%#", [fmt stringFromDate:endOfWeek]);
Some notes:
cal.firstWeekday gives the locale dependent index of the first weekday, e.g.
2 = Monday in Germany, or 1 = Sunday in the U.S. Depending on your needs,
you can also use a constant value here.
It might be necessary to set cal.minimumDaysInFirstWeek, compare
NSDateFormatter reports June 2, 2013 as being in week zero.
The dateByAddingUnit:... method is available in OS X 10.9 or later.
Alternatively, use dateByAddingComponents:....
I have assumed that you use the Gregorian calendar, so that a week has 7 days.
Alternatively, you can add one week and then subtract one day.

Array of times for each day of the week in iOS

I have times that I would like to compare to the current time for each day of the week. From what I've come across, it sounds like the best thing to do would be to have an array for each day of the week with the given times I want. For example:
mondayTimes(2:00:00, 5:00:00, 9:00:00, 14:00:00)
tuesdayTimes(3:00:00, 6:00:00, 10:00:00, 15:00:00)
etc...
I want to find out the given day of the week using the current date, and then depending on what day it is, use the array of times for that given day. Then use the current time to find which time is next in the array.
Basically it is like an "alarm clock" that always has set times for every day of the week.
Do I use NSStrings to populate the dates in each array and convert them so I am able to compare them to the current time? What is the best route to go about this?
Thanks!
To get the current date, use NSDate currentDate = [NSDate date];
Then, to extract the weekday: initialize a NSCalendar of your choice, then call [calendar components:NSWeekdayCalendarUnit fromDate:currentDate];, where calendar is your calendar instance.
This produces a number between 1 and 7 (for the Gregorian calendar) where 1 is Sunday and 7 is Saturday. I would then advise you put all of your times in an array of arrays, with the 1 index containing an array of your sundayTimes, 2 containing an array of mondayTimes, ... 7 containing an array of your saturdayTimes.
Then using [allTimes objectAtIndex weekday] will return a NSArray of your times. All that's left is to compare the times, which I'm sure you can figure out.

Setting and Retrieving Dates in iOS that avoid issues with timezone changes

I have a "time-tracking" app that allows a user to create an entry on whichever days a user desires but only one permitted per day. I store these entries into CoreData.
[rateObject setValue:[Day dateWithHour:currentDate forHour:12] forKey:#"date"];
Later, I retrieve these entries using the following code.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Day"];
request.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"date" ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:#"whoWorked == %# && date => %# && date =< %#", whoWorked, [Day dateWithHour:fromDate forHour:0], [Day dateWithHour:toDate forHour:24]];
As you can see I placed the entry in the middle of the day (12 hours) and retrieved the dates from start of the first day (0 hours) and end of the last day (24 hours).
This is a hack which seems to work when I only shift timezones by a few hours or switch for Standard Time to Daylight Savings. It falls apart when I move from NA to Europe i.e. the entries in the old timezone appear on different days in the retrieval.
What I want to get to is an entry made on April 25, 2014 appears on April 25, 2014 no matter what timezone I am currently in.
I have looked at a number of sources to understand NSDate, NSDateComponents, NSCalendar etc but can't seem to land on a good understanding that will allow me to implement this correctly or cleanly. Any advice appreciated.
Here is my method for creating a date with a specific hour (in Day).
+ (NSDate *)dateWithHour:(NSDate *)date forHour:(int)hour {
// Create and initialize date component instance
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit fromDate:date];
if (hour<0) hour = 0;
else if (hour>24) hour = 24;
[dateComponents setHour:hour];
// Create period dates
NSDate *newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
return newDate;
}
The best to use time-zone and platform independent is the timestamp, which you can get from NSDate as well. With that you can easily do calculations with Time-intervals. If you want to have a specific date it is always related to the time zone of the user. Then you can convert the timestamp into a user-formatted date. Like mentioned by Zaph he might want to see the date where he currently is. Again with the timestamp this is always reliable.
If you want to calculate that an entry can be done only once per calendar day in the location where somebody is, then you can calculate with ˙NSCalendar˙ and ˙NSDateComponents˙ for example what day a timestamp represents and then from the beginning of that day calculate 24 hours up. Conversion back to a timestamp gives you a helpful range for check if something is within the same calendar day. The NSCalendar is the base for calculation even if you will probably use Gregorian most of the time. With the NSDateComponentsyou can what ever part you want from your Timestamp (e. g. only the day, the month, the year, etc.).

iPhone OS4.3: NSCalendar's [ordinalityOfUnit:inUnit:forDate:] method returns different/wrong result

I've following code snippet which I'm using to deduce the first day of the week, to display in my calendar view. This code has been working without any issue, till I tested it on iPhone OS 4.3 onwards.
int firstDOW = [m_calendar ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:fom]%7;
where 'fom' is the first date of the month.
When debugged the code, on iOS prior to 4.3, return value for 'ordinality' method seems to return correct value( for example if the 'fom' date falls on Friday, the value returned from above method is '5'). But on iOS >= 4.3, the return value is somehow not the correct weekday( for example, if the 'fom' date falls on Friday, the value returned from above method is '6'!).
I don't understand, whether there is any issue with my code, or it really is a bug in the above method.
Has anyone else faced this in iOS >= 4.3??
Thanks and Regards.
I learned a bit more about this method call. It appears that the ordinalityOfUnit:inUnit:forDate: method pays attention to what current locale is and what that locale considers the first day of the week to be.
For example. In the United States locale the first day of the week is considered to be Sunday while in the Ireland locale, the first day of the week is considered to be Monday.
If you are in the US locale, and ask for the ordinality of Tuesday, it will return 2 (0 for Sunday, 1 for Monday and 2 for Tuesday). In the Ireland locale, however, it will return 1 (0 for Monday and 1 for Tuesday).
In short, the ordinality of the day within the week depends on which day is considered to begin the week. In contrast, if you use the NSDateComponents API and get the day of the week from there, you always get a day relative to Sunday === 0. e.g.
NSDateComponents *components = [[self calendar] components: NSWeekdayCalendarUnit fromDate: [self startingDay]];
NSUInteger weekdayIndex = [components weekday];

Resources