Im changing text value based on the day of the week, I was able to achieve this using string values, however I want to be able to achieve on a numeric value instead - to remove issues with different languages. For example, if today is monday do... but I want if today is day 1 then do. Ive tried the code below but it gives me a numeric value of 0;
NSDateFormatter *dayofweekformatter = [[NSDateFormatter alloc] init];
[dayofweekformatter setDateFormat:#"E"];
NSString *DayOfWeek = [dayofweekformatter stringFromDate:[NSDate date]];
NSInteger weekDay = [DayOfWeek integerValue];
NSLog(#"The day of the week is: %d", weekDay);
Is it possible to do this?
According to this link, "E" on its own will give you the day of the week as a textual format, i.e.: "Mon"/"Tue" etc.
If you want the day of the week as an integer, you should use a lower case "e" or "c".
A different implementation would be to use NSCalendar and NSDateComponents to determine the day of the week as this is more likely to take into consideration different settings across different devices based on the users preferred calendar.
NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitWeekday fromDate:date];
NSLog(#"day of the week: %i", [dateComponents weekday]);
Here is solution proposed on Apple forums https://discussions.apple.com/thread/1700102?start=0&tstart=0 (I am not the author)
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents =[gregorian components:NSWeekdayCalendarUnit fromDate:dateOfInterest];
NSInteger weekday = [weekdayComponents weekday];
// weekday 1 = Sunday for Gregorian calendar
[gregorian release];
Related
I want to get how many seconds are remaining to complete an hour. No matter which what time it is?
if its 05:01:00 then it should give 3540 seconds
and if its 11:58:40 then it gives 80 seconds and so on. I try to find it on google but could not able to find it.
Thanks in advance.
NSCalendar has got methods to do that kind of date math:
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
// find next date where the minutes are zero
NSDate *nextHour = [calendar nextDateAfterDate:now matchingUnit:NSCalendarUnitMinute value:0 options:NSCalendarMatchNextTime];
// get the number of seconds between now and next hour
NSDateComponents *componentsToNextHour = [calendar components:NSCalendarUnitSecond fromDate:now toDate:nextHour options:0];
NSLog(#"%ld", componentsToNextHour.second);
#Vadian's answer is very good. (voted)
It requires iOS 8 or later however.
There are other ways you could do this using NSCalendar and NSDateComponents that would work with older OS versions.
You could use componentsFromDate to get the month, day, year, and hour from the current date, then increment the hour value and use the NSCalendar method dateFromComponents: to convert your to adjusted components back to a date.
NSDate *date1 = [NSDate dateWithString:#"2010-01-01 00:00:00 +0000"];
NSDate *date2 = [NSDate dateWithString:#"2010-02-03 00:00:00 +0000"];
NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];
Fill in with the correct times and dates to get the difference in seconds
Edit: An alternative method is to work out the currenthour and return as an integer. Then add one to the NSInteger returned as below (you will have to make sure to handle the case where it is after midnight though!)
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger currentHour = [components hour];
I am trying to determine if the current date is in fact three days or less from the end of the month. In other words, if I am in August, then I would like to be alerted if it is the 28,29,30, or 31st. If I am in February, then I would like to be notified when it is the 25,26,27, or 28 (or even 29). In the case of a leap year, I would be alerted from 26th onwards.
My problem is that I am not sure how to perform such a check so that it works for any month. Here is my code that I have thus far:
-(BOOL)monthEndCheck {
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
if (month is 3 days or less from the end of the month for any month) {
return YES;
} else {
return NO;
}
}
Because there are months with 28, 30, and 31 days, I would like a dynamic solution, rather than creating a whole series of if/else statements for each and every condition. Is there a way to do this?
This is how you get the last day of the month:
NSDate *curDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:curDate]; // Get necessary date components
// set last of month
[comps setMonth:[comps month]+1];
[comps setDay:0];
NSDate *tDateMonth = [calendar dateFromComponents:comps];
NSLog(#"%#", tDateMonth);
Source: Getting the last day of a month
EDIT (another source): How to retrive Last date of month give month as parameter in iphone
Now you can simply count from the current date.
If < 3 do whatever you wanted to do.
Maybe something like this:
NSTimeInterval distanceBetweenDates = [date1 timeIntervalSinceDate:date2];
double timeInSecondsFor3Days = 280000; //Better use NSDateComponents here!
NSInteger hoursBetweenDates = distanceBetweenDates / timeInSecondsFor3Days;
However I did not test that^^
EDIT: Thanks to Aaron. Do NSDateComponents to calculate the time for three days instead!
First you have to compute the start of the current day (i.e. today at 00.00).
Otherwise, the current day will not count as a full day when computing the
difference between today and the start of the next month.
NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *startOfToday;
[cal rangeOfUnit:NSCalendarUnitDay startDate:&startOfToday interval:NULL forDate:now];
Computing the start of the next month can be done with rangeOfUnit:...
(using a "statement expression" to be fancy :)
NSDate *startOfNextMonth = ({
NSDate *startOfThisMonth;
NSTimeInterval lengthOfThisMonth;
[cal rangeOfUnit:NSCalendarUnitMonth startDate:&startOfThisMonth interval:&lengthOfThisMonth forDate:now];
[startOfThisMonth dateByAddingTimeInterval:lengthOfThisMonth];
});
And finally the difference in days:
NSDateComponents *comp = [cal components:NSCalendarUnitDay fromDate:startOfToday toDate:startOfNextMonth options:0];
if (comp.day < 4) {
// ...
}
Given an NSDate, how do I find the first day of that date's week, given the user's locale. For example, I've heard that some countries treat Monday as the first day of the week and others use Sunday. I need to return the preceding Monday in the first case but the preceding Sunday in the latter case.
My best effort thus far always returns the preceding Sunday, regardless of the device settings applied:
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setLocale:[NSLocale currentLocale]];
NSDateComponents *components = [calendar components:NSYearForWeekOfYearCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit fromDate:originalDate];
[components setWeekday:1];
NSDate *firstDayOfWeek = [calendar dateFromComponents:components];
Bonus question: on iOS, which setting drives this? Is it the 'Region Format'?
Try changing:
[components setWeekday:1];
to:
[components setWeekday:[calendar firstWeekday]];
You should also remove the NSYearForWeekOfYearCalendarUnit and NSWeekCalendarUnit components.
Bonus Question: "Region Format" should be the setting that changes the first day of the week.
An smarter way for old style for those who do not want to set calendar firstWeekday.
NSDate *date = [NSDate dateWithTimeIntervalSince1970:1483620311.228];
NSLog(#"current date ===> : %#", date);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *previousMonday = [calendar nextDateAfterDate:date
matchingUnit:NSCalendarUnitWeekday
value:2 //use 1-7 for Sunday to Saturday week day.
options:NSCalendarMatchNextTime | NSCalendarSearchBackwards];
NSLog(#"previousMonday date ===> : %#", previousMonday);
Is there any way to find out an accurate difference between two NSDate?
I have found solutions but they aren't accurate enough. I need to take into account daylight saving, the fact that different months have a different number of days, etc.
A simple calculation such as /60/60/24 etc. to work out minutes, hours and days doesn't take them into account.
Lets say I need to work out the difference between the time right now ([NSDate date]) and December 25th 10:22PM (date chosen by user using date picker [datePicker date]) just as an example, how would I do this?
Knowing the exact time difference isn't the key, so long as I have an accurate difference of days, months and years, it will do.
From Apple's Date & Time Programming Guide:
Listing 12 Getting the difference between two dates
NSDate *startDate = ...;
NSDate *endDate = ...;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:startDate
toDate:endDate options:0];
NSInteger months = [components month];
NSInteger days = [components day];
NSDate is completely independent of Timezone. Daylight saving doesn't even come into the picture for NSDate. Only when you convert NSDate into a human readable format (MM/DD/YY, HH:MM:SS format or the like), does Time Zone come into picture.
Make sure that you take into account correct timezone, day-light saving setting when you create NSDate(s). Subsequently, the method, [date1 timeIntervalSinceDate:date2] should always give you accurate time difference.
So, the more accurate question you meant to ask was: How can I get a nicely formatted days, months, years from a difference between two dates. First you want to get the nsTimerInterval (time difference in seconds) and then format it:
How do I break down an NSTimeInterval into year, months, days, hours, minutes and seconds on iPhone?
Small update on the code for latest iOS:
NSDate *startDate = ...;
NSDate *endDate = ...;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSUInteger unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *components = [gregorian components:unitFlags
fromDate: startDate
toDate:endDate options:0];
NSInteger months = [components month];
NSInteger days = [components day];
e.g. 01.10.2010 is friday => 27.09.2010 is monday.
I have no idea how to manage this one. btw: how can I calculate with dates?
For time/date calculations use NSDateComponents.
Listing 2 Getting the Sunday in the current week
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Get the weekday component of the current date
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:today];
/*
Create a date components to represent the number of days to subtract from the current date.
The weekday value for Sunday in the Gregorian calendar is 1, so subtract 1 from the number of days to subtract from the date in question. (If today's Sunday, subtract 0 days.)
*/
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
[componentsToSubtract setDay: 0 - ([weekdayComponents weekday] - 1)];
NSDate *beginningOfWeek = [gregorian dateByAddingComponents:componentsToSubtract toDate:today options:0];
/*
Optional step:
beginningOfWeek now has the same hour, minute, and second as the original date (today).
To normalize to midnight, extract the year, month, and day components and create a new date from those components.
*/
NSDateComponents *components =
[gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate: beginningOfWeek];
beginningOfWeek = [gregorian dateFromComponents:components];
In later versions, there is a smarter way:
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setFirstWeekday:2]; //2 is monday. 1:Sunday .. 7:Saturday don't set it, if user's locale should determine the start of a week
NSDate *now = [NSDate date];
NSDate *monday;
[cal rangeOfUnit:NSWeekCalendarUnit // we want to have the start of the week
startDate:&monday // we will write the date object to monday
interval:NULL // we don't care for the seconds a week has
forDate:now]; // we want the monday of today's week
If you actually change the weekday that represents the start of the week (Sunday vs. Monday), you should change it back after this snippet.