How to get get a month and date in Objective C? - ios

I am a new to objective C, I am developing a app to determine the date of birth when user gives the year and the number of days. For example if user give 1985 as his/her year of birth and the number of days as 311. his/here date of birth is 1985 November 6. So how to get the November 6 from 311 in 1985 ? Please help

You should never have to calculate whether the current year is a leap year or not. Never ever ever. Let the frameworks do that for you. People much more intelligent than you or I have done this for us already, so why on earth would we go about re-inventing this wheel with sub-optimal algorithms that would never account for all of the intricate calendar variations?
It's stupid to do this yourself. So don't:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *startComponents = [[NSDateComponents alloc] init];
[startComponents setYear:1985];
[startComponents setDay:311];
NSDate *date = [gregorian dateFromComponents:startComponents];
NSLog(#"endDate: %#", date);
This logs:
endDate: 1985-11-07 08:00:00 +0000

Something like this (not tested):
NSDateFormatter *df = [[NSDateFormatter alloc] init] autorelease];
[df setDateFormat:#"yyyy"];
NSDate *date1 = [df dateWithString:#"1985"];
NSDate *date2 = [df dateByAddingTimeInterval:60*60*24*311]; //

First off, why are you getting the number of days from someone instead of getting the month and day. Users will not know what day of the year they are born and will be frustrated to try and figure it out.
To answer your question, you could have an array that stores the number of days at the end of each month {31, 28, 31, 30, ...} and use that as a reference (subtracting the total in a loop). You'll also have to check if the year was a leap year and subtract one from the total if its over 59.

You don't need anything specific from Objective-C... first you need to know if the year is a leap year. Then you need to count the days from the months until you end with your target day.

Related

Setting a minimum and maximum month in iOS date picker, but should update the picker view

When you select the date field in a view, the date picker displays. I want to limit the scroll from a minimum 2 months less than current month and a maximum 4 months more than current month. I have seen similar examples. For example: for current month November, the month range should be September - March next year.
I tested this example, but wasn't successful.
// Configure date picker
- (void) initializeDatePicker {
_datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 600, 160)];
_datePicker.backgroundColor = [UIColor whiteColor];
_datePicker.datePickerMode = UIDatePickerModeDate;
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *currentDate = [NSDate date];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setMonth:-2];
NSDate *minDate = [gregorian dateByAddingComponents:comps toDate:currentDate options:0];
[comps setMonth:4];
NSDate *maxDate = [gregorian dateByAddingComponents:comps toDate:currentDate options:0];
_datePicker.minimumDate = minDate;
_datePicker.maximumDate = maxDate;
[_datePicker addTarget:self action:#selector(datePickerValueChanged:) forControlEvents:UIControlEventValueChanged];
[_txfDateTextField setInputView:_datePicker];
selectedDate =[NSDate date];
}
UPDATE:
The above code updates the date picker object. However, the problem is that there is no change in the date picker view. For the example above, I want the scroll to limit scrolling from September to March next year. This way the user doesn't get overwhelmed when he is scrolling. From a better UX point of view.
Ok, based on an extended discussion, I now understand that the goal is to remove months that are outside of the range.
You can't do it with a standard date picker. You would have to build a custom control using a UIPickerView.
The short answer is, "Don't do that."
If you want to allow 2 months back, and 4 months forward:
If your current date is November, 2016:
Valid months are September, October, November 2016, December 2016, and January, February, and March 2017.
So if the user selects 2016, you'd need to populate the month picker wheel with September, October, November. Then if the user switches to 2017, you'd need to rebuild the month wheel with only January, February, and March.
But, now you're not using a date picker, you're using a UIPickerViewthat you want to act like a date picker.
So in addition to rebuilding the month spinner based on the current year, you have to manage setting up the day picker to show the valid days for the currently selected year and month. Most months have 30 or 31 days, but what about February? What about leap years? What about centuries, which aren't leap years?
Plus, you're building a control that looks like a date picker, and sort of, but not quite, acts like a date picker.
Are you going handle calendars other than Gregorian? What about Hebrew, Arabic, Chinese calendars? The burden is on you to make all of that work correctly.
Apple has spent a LOT of money on usability studies and come up with a standard control that works well, and does handle localization for different calendar systems, etc, etc.
In short, this is a rabbit hole you do not want to descend into.

ios/xcode/objective-c: Display future dates in friendly format

I have found some great solutions for displaying past dates in user friendly format such as just now, a few hours ago, yesterday, last week etc.
However, I've been unable to find a similar friendly format for future events/appointments.
I'm looking for something like, Today at 2PM. Tomorrow, Wednesday at 3:45PM. next Tuesday, September, 12th at 2PM. or for further away dates Friday, November 12th, 2015 at 2PM.
Can anyone recommend a category that does this, a tutorial or provide guidance in the form of a method to tackle this?
Thanks in advance for any suggestions.
Best user friendly date :
The solution is the same. You can build your solution on the link you mentioned.
[[NSDate date] timeIntervalSinceDate:date]; is a simple subtraction between two date who return positive or negative double if date is in the past or the futur.
After verifying if the date is in the past or the future some mathematics will give you the good user friendly string. For example, you can change the format depending on the parameters.
Simple user friendly :
If what you want is always string like "Wednesday, November 15th at 02:00PM", you can use NSDateFormater.
For your case :
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEEE, MMMM dd 'at' HH:mma"];
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:162000];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
With this method date string will always take the same format.
Hope that's will help.

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.

NSDate dateFromString 2 months wrong?

I have the following code:
NSDateFormatter *dateFormater = [[NSDateFormatter alloc] init];
[dateFormater setDateFormat:#"yyyy-MM-DD HH:mm:ss"];
[dateFormater setLocale:[NSLocale currentLocale]];
[dateFormater setTimeZone:[NSTimeZone systemTimeZone]];
NSDate *localDate = [dateFormater dateFromString:localUpdate];
NSDate *serverDate = [dateFormater dateFromString:serverUpdate];
The input strings for localUpdate and serverUpdate are:
2014-01-31 23:42:17
2014-02-01 00:09:37
When converting those from NSString to NSDate, the second one is 2 months behind?
2014-01-31 22:42:17 +0000
2013-12-31 23:09:37 +0000
Can anyone explain this?
check this line:
[dateFormater setDateFormat:#"yyyy-MM-DD HH:mm:ss"];
the correct date format is #"yyyy-MM-dd HH:mm:ss" with "dd" not "DD"
I had the same problem once... and if the date format it's incorrect, when you use the dateFormatter, it will subtract or add one month to the date.
Your date format string "yyyy-MM-DD HH:mm:ss" is not quite right.
You're telling NSDateFormatter to parse the 01 in your second example as the day of the year (DD) instead of the day of the month (dd), which you want instead.
yyyy-MM-DD HH:mm:ss
2014-02-01 00:09:37
^^~~~~~~~~~~~ these digits are being parsed as day of year rather
than as day of month
This is an easy mistake, and one that is confusingly hidden by your first example, in which the day of month and the day of year are the same.
See the Unicode reference for the date formats used by iOS 6 and up. (For older versions, choose the right link in Apple's documentation.)
Academic tangent: why NSDateFormatter interprets the second date as being on the last day of 2013 (rather than 1st day of 2014, as specified) is probably a bug caused by specifying a month and a day of year (which are mutually exclusive), a bug in the parser (interpreting the -01th day of the year), or a timezone or daylight savings detail (if the rules changed on midnight in the local timezone.)

Compute number of weeks since epoch more accurately than days/7

I'm putting together a game where there's a tournament every week, and every week there's a different special bonus for the game.
To make this work I need to know which week it is so I can select the right bonus, and make sure the score goes to the right tournament.
A trivial answer is to take the number of days since epoch, offset to get to a monday, then compute the number of days and divide by 7. Obviously this fails because of leap year.
Another option would be to figure out which week of the year you're on, but that gets weird when you transition from one year to the next. Also, the tournament ends at the end of the day on Sunday, so it doesn't follow the normal week borders.
I was about to start doing some fairly complicated stuff using the year, day of year and day of week to try to figure it out, but I thought I'd ask here in case there was an easy solution I was missing.
This will be done in Objective-C on iOS.
This should work:
// Choose any reference date which is a Monday:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *refComp = [[NSDateComponents alloc] init];
refComp.year = 1970;
refComp.month = 1;
refComp.day = 5;
NSDate *refDate = [cal dateFromComponents:refComp];
// Compute number of weeks between your date and the reference date:
NSDateComponents *comp = [cal components:NSCalendarUnitWeekOfYear fromDate:refDate toDate:yourDate options:0];
NSInteger weeks = comp.weekOfYear;
But calculating the number of days (since some Monday) and dividing by 7 should
give the same result because every week has 7 days, regardless of leap years.

Resources