Objective C - How can i get the weekday from NSDate? - objective-c

I need to be able to get the weekday from nsdate, i have the following code and it always return 1. I tried to change the month, i tried everything from 1 to 12 but the result of the week day is always 1.
NSDate *date2 = [[NSDate alloc] initWithString:[NSString stringWithFormat:#"%d-%d-%d", 2010, 6, 1]];
unsigned units2 = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit;
NSCalendar *calendar2 = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components2 = [calendar2 components:units2 fromDate:date2];
int startWeekDay = [components2 weekday];
[date2 release];
[calendar2 release];

Creating an NSDateFormatter that only contains the weekday will do what you want.
NSDate *now = [NSDate date];
NSDateFormatter *weekday = [[[NSDateFormatter alloc] init] autorelease];
[weekday setDateFormat: #"EEEE"];
NSLog(#"The day of the week is: %#", [weekday stringFromDate:now]);
If you need internationalization, the NSDateFormatter can be sent a locale, which will give the proper translation.
The date formatters are controlled through this standard: Unicode Date Formats

Edit for Mac:
The format of the string has to be —YYYY-MM-DD HH:MM:SS ±HHMM according to the docs, all fields mandatory
Old answer (for iPhone and tested on simulator):
There is no (public) -initWithString: method in NSDate, and what you get returned is not what you expect.
Use a properly configured (you need to give the input format) NSDateFormatter and -dateFromString:.

I solved the problem, The problem was that the format of my date string was wrong:
NSDate *date = [[NSDate alloc] initWithString:[NSString stringWithFormat:#"%d-%d-%d 10:45:32 +0600", selectedYear, selectedMonth, selectedDay]];
and since i don't care about the time i randomly pass a time to the end of the string

I'm using Xcode 6.4
There are many ways to setup an NSDate. I won't go over that here. You've done it one way, using a string (A method I avoid due to it being very vulnerable to error), and I'm setting it another way. Regardless, access your components weekday or setDay methods.
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
[calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en-US"]];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitWeekday|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond) fromDate:[NSDate date]];
NSDate *date = [calendar dateFromComponents:components];
this way, you can get or set any of these components like this:
[components weekday] //to get, then doSomething
[components setDay:6]; //to set
and, of course, set NSDate *date = [calendar dateFromComponents:components];only after you've changed the components.
I added in the extra local and other components for context in case you'd like to set those too.
It's free code, don't knock it.

Anyone coming here looking for a more recent Swift 4 solution:
extension Date {
func getDayOfWeek() -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone.current
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.setLocalizedDateFormatFromTemplate("EEEE")
return dateFormatter.string(from: self)
}
}
let inputString = "2018-04-16T15:47:39.000Z"
let result = inputString.getDayOfWeek()
result = Monday

Most upvoting answer in Swift 3.
let formatter = DateFormatter()
formatter.dateFormat = "EEEE"
print("The day of the week is \(formatter.string(from: Date()))")

I used the following website which helped with setting up the string to retrieve the format I wanted on my date
Coder Wall - Guide to objective c date formatting

Related

Convert the exact NSString value to NSDate [duplicate]

This question already has an answer here:
returns a date an hour in the future
(1 answer)
Closed 7 years ago.
This is my code.
NSString *dateString = #"2015-06-03 02:19:37";
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSLog(#"converted date = %#",[formatter dateFromString:dateString]);
The output of the code above is: "converted date = 2015-06-02 18:19:37 +0000". I know that this is because it converts the NSString with respect to GMT, but what i wanted to happen is NSDate must be 2015-06-03 02:19:37, same with dateString
I know that this is because [the NSDateFormatter] converts the NSString with respect to GMT…
No, you're wrong. NSDateFormatter defaults to using your current time zone.
What you're not understanding is that "2015-06-02 18:19:37 +0000" is the same date and time as "2015-06-03 02:19:37" (in your local time zone, which must be GMT+0800).
Also, the description that you logged is just one representation of the date. The date does not have a year, month, day-of-month, hour, minute, second, or any of that. A date object just represents a moment in time. Such moments don't have any of that and neither do NSDate objects. Only representations of moments have those things, and they are only arrived at by processing the date through a specific calendar and time zone. In any case, any given date has multiple representations. Just because the description that gets logged happens to choose a representation that you weren't expecting doesn't mean the date is wrong.
You have implicitly requested a conversion from an NSDate object to a string when you logged it. That's because logging always involves strings. The string-formatting code used by NSLog() and the %# format specifier uses the -description method. You are never going to be able to force NSDate's implementation of -description to use your time zone, so don't try.
If you really need a string representation (and you're not just debugging) and you want it in some specific time zone or otherwise want to dictate the format, don't rely on the -description method like you are. Instead, use a date formatter to convert from NSDate to an NSString explicitly, and configure the date formatter to produce the representation that you want.
But don't confuse the need to do that with the date being wrong.
What I really wanted to do is to check if the given NSDate is already past 9PM EST (-4GMT), while i'm on +8GMT timezone.
So, use NSCalendar, NSTimeZone, and NSDateComponents to construct an NSDate for 9PM EST (on the current day, I suppose you mean) and then compare the dates.
NSDate* date = /* ... */;
NSCalendar* calendar = [[NSCalendar alloc] initWithIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
NSDate* deadline = [calendar dateBySettingHour:21 minute:0 second:0 ofDate:date options:0];
if ([date compare:deadline] == NSOrderedDescending)
/* date is after deadline */;
Here I used the convenience method -dateBySettingHour:minute:second:ofDate:options: and avoided direct use of NSDateComponents. If your needs differ, you might have to convert the date to date components using the calender, modify the components, convert them back to a date, and then compare.
Use the NSDateComponents class to build the date from the information in the string. The documentation explicitly provides an example of this:
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];
NSDateComponents *weekdayComponents =
[gregorian components:NSWeekdayCalendarUnit fromDate:date];
int weekday = [weekdayComponents weekday];
call this method with your string value...
- (NSDate *)dateFromString:(NSString *)date
{
static NSDateFormatter *dateFormatter;
if (!dateFormatter)
{
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
}
NSLog(#"Date: %#",date);
return [dateFormatter dateFromString:date];
}
RESULT : Date: 2015-06-03 02:19:37
NSString *dateString = #"2015-06-03 02:19:37";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [f dateFromString:dateString];
You will get the NSDate here(startDate).... May this help to you.....

How to compare two times in iOS

I am trying to compare two times in iOS. I have list of times in my array i just want to check current time is matching to the any one the array value. can any help how to do that. i searched whole internet i did't get any idea.
I saw this question answer but i can't get a exact result.
According to Apple documentation of NSDate compare:
Returns an NSComparisonResult value that indicates the temporal ordering of the receiver and another given date.
- (NSComparisonResult)compare:(NSDate *)anotherDate
Parameters anotherDate
The date with which to compare the receiver. This value must not be nil.
Return Value
If:
The receiver and anotherDate are exactly equal to each other, NSOrderedSame
The receiver is later in time than anotherDate, NSOrderedDescending
The receiver is earlier in time than anotherDate, NSOrderedAscending
In other words:
if ([date1 compare:date2]==NSOrderedSame) ...
Note that it might be easier to read and write this :
if ([date2 isEqualToDate:date2]) ...
-(NSString *)determineDateFromstring:(long long)date
{
NSTimeInterval interval=date;
NSDate *currentTime=[NSDate dateWithTimeIntervalSince1970:interval/1000];
NSLocale *gbLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_GB"];
NSNumber *myDateInString=[NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970]*1000];
NSTimeInterval inte=[myDateInString longLongValue];
NSDate *todayTime=[NSDate dateWithTimeIntervalSince1970:inte/1000];
NSCalendar *currentcalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [currentcalendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:todayTime];
int currentday=[components day];
int currentyear=[components year];
NSCalendar *paramtercalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *parametercomponents = [paramtercalendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:currentTime];
int currentday1=[parametercomponents day];
int currentyear1=[parametercomponents year];
if (currentday==currentday1) {
Nslog(date are same);
}else if(currentyear==currentyear1) {
Nslog(year are same);
}else{
}
}
if u want to check two date are equal or not then u can compare NStimeIntervals(long long values). if same then time ,date and year are same otherwise different.
I hope this answer will be the right to your question.......
Why don't you check the interval since 1970 and compare the integer value..
long long int i = [[NSDate date] timeIntervalSince1970];
I hope this will help.Also if you have values in form of NSString then you first need to convert them to NSDate
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ssSSSSSS";
NSDate *d = [dateFormatter dateFromString:#"your date string"];

Struggling to store a date for later use

Hi I'm very new to iOS programming and am playing around with dates (todays date and a date 1 year from now).
Here's the code i'm dabbling with.
NSCalendar * calendar = [NSCalendar currentCalendar];//Create a calendar
NSDate *todaysDate = [[NSDate alloc]init]; //get todays date
NSString *dateToday = [NSString stringWithFormat:#"%#",todaysDate];//convert it to a string
NSDateFormatter *df = [[NSDateFormatter alloc] init];// create a formatter
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss ZZZ" ];//input how the date looks as a string
myDate = [df dateFromString: dateToday];// change it back to a proper NSDate
NSDateComponents *components = [[NSDateComponents alloc] init]; // create the components
[components setYear:1];//add 1 year
nextYear = [calendar dateByAddingComponents:components toDate:todaysDate options:0]; // build the year from component into a variable
dateNextYear = [NSString stringWithFormat:#"%#",nextYear];//convert it to a string
NSDateFormatter *yearFormat = [[NSDateFormatter alloc] init];// create a formatter
[yearFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss ZZZ" ];//input how the date looks as a string
myDateInTheFuture = [yearFormat dateFromString: dateNextYear];// change it back to a proper NSDate
NSLog(#" next years date is %# ", myDateInTheFuture);
[yearFormat release];
[components release];
[todaysDate release];
I can get the current date and the future date 1 year from now, but i'm unsure how i would store the future date for comparison, i know i can use the "compare" item for NSDate to check, but when i set the future date to a variable every time it runs it stays relative 1 year apart from what i'm checking it against which is todays date.
Its 3am where i am and my brain is mush so apologises in advance if this is the simplest thing ever and i just can't see it.
Its my first post so go easy on me please.
Thanks
I am not entirely sure what you are trying to do, but this is what I gather:
You want to take the current date, add a year to it, and manipulate the resulting date.
Please notify me if this is not correct.
For this, try the following:
NSDate *todayDate = [NSDate date]; //Create a date that is set to today
NSDate *resultingDate = [calendar dateByAddingTimeInterval:31556926; //Take the current date and add the amount of seconds in a year to it
If you want to store this permanently, use the NSUserDefaults:
to set:
[userDefaults setObject:resultingDate forKey:#"storedDate"];
Hope this helps,
HBhargava
to get:
NSDate *returnedDate = [userDefaults dateForKey:#"storedDate"];

NSDate won't load/display correctly

I'm not sure what's going on with this. I'm trying to load an NSString* object from a file, convert it to an NSDate* with a date formatter, and then convert the hour and minute components back to NSString so I can display a time in Interface Builder. However, instead of the time that was saved to the file, instead I end up with 19 for the hour, and 0 for the minute. (Regardless of what was put in, the program loads four different NSDates)
Here's the code for loading the date from the file (I checked with breakpoints, and the array does indeed have the correct data, so that's not the problem)
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd hh:mm:ss a"];
date1 = [[df dateFromString:[loadArray objectAtIndex:3]] retain];
Here's the code for displaying the date.
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comp = [[gregorian components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:myDrug.date1] retain];
hourField1.text = [NSString stringWithFormat:#"%d", comp.hour];
minuteField1.text = [NSString stringWithFormat:#"%d", comp.minute];
(hourField1 and minuteField1 are the IBOutlets that receive the values, by the way)
I'm not sure where I've gone wrong here, and any help would be greatly appreciated. Thanks!
Update:
On the suggestion of some of the people here, I've NSLogged the problem, and I've found that it the date formatter that's not working. An example date is 2011-02-14 06:00:00 GMT, and the date formatter is yyyy-MM-dd hh:mm:ss a, so I'm not sure why it won't work.
If the date strings in loadArray are of the form 2011-02-14 06:00:00 GMT, then the format should be set as follows:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss zzz"]; <--
date1 = [[df dateFromString:[loadArray objectAtIndex:3]] retain];
// the retain above is suspicious btw (but that's another question)
[df release]; //don't forget this
I also changed the hh to HH assuming that the hours are actually in 24-hour instead of 12-hour format. See Unicode Date Format Patterns for details.
Next, when displaying the date, if you want to show the hours and minutes in GMT instead of whatever the user's current time zone is, you'll need to set the calendar's time zone:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:#"GMT"]; <--
[gregorian setTimeZone:tz]; <--
NSDateComponents *comp = [gregorian components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:myDrug.date1];
//do not do a retain on comp above
hourField1.text = [NSString stringWithFormat:#"%d", comp.hour];
minuteField1.text = [NSString stringWithFormat:#"%d", comp.minute];
[gregorian release]; //don't forget this

What's the best/easiest way to compare two times in Objective-C?

I've got a string representation of a time, like "11:13 AM." This was produced using an NSDateFormatter and the stringFromDate: method.
I'd like to compare this time to the current time, but when I use the dateFromString: method to turn the string back into a date, a year, month and day are added - which I don't want. I just need to know if right now is < or > the time stored in the string.
What's going to be the best way to handle that? Thanks in advance for your help.
Instead of using the string representation, use the NSDate you got from the picker. You can convert that hour/min/sec using NSDateComponents, then also convert [NSDate date] to NSDateComponents. Compare the hours/minutes/seconds of the two sets of components.
EDIT -- use a utility function for things like this that converts the hr/min/sec components of NSDate into a secondsOfTheDay (seconds since midnight).
You can directly use two time of day values since they are both seconds since midnight. Simple integers can be easily compared and stored and manipulated. You don't have to use NSDate all the time.
//----------------------------------------------------------------------------
// extracts hour/minutes/seconds from NSDate, converts to seconds since midnight
//----------------------------------------------------------------------------
unsigned secondOfTheDay( NSDate* time )
{
NSCalendar* curCalendar = [NSCalendar currentCalendar];
const unsigned units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* comps = [curCalendar components:units fromDate:time];
int hour = [comps hour];
int min = [comps minute];
int sec = [comps second];
return ((hour * 60) + min) * 60 + sec;
}
If I understand the problem correctly, you’re using the dateFromString: method of NSDateFormatter. This is giving you the correct time, but with a default date of January 1, 1970, which is useless to compare against the current date/time.
This is easy to solve. Use setDefaultDate: to set the default date to today.
NSDate *now = [NSDate date];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"hh:mm a"];
[formatter setDefaultDate:now];
NSDate *theDate = [formatter dateFromString:#"11:13 AM"];
NSComparisonResult theResult = [theDate compare:now];
Can you reuse the string formatter that you used to create the string? So, let's say you created the string like this:
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm a"];
NSString *dateAsString = [formatter stringFromDate:[NSDate date]];
You can get an NSDate like this:
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm a"];
NSDate *date = [formatter dateFromString:dateAsString];
The day, month, year and timezone information will not be kept, but you'll have an NSDate object with the values of 1/1/1970 and GMT for the timezone offset.
At this point you can use the compare: (which is typically reserved for sorting operations) or the laterDate: or earlierDate: methods.
Be careful using NSDateFormatter like this, as you may run into issues with internationalization.
If you need to add information about the current date to the date you get from dateFromString:, such as the month day and year, you'll need to use NSCalendar's dateByAddingComponents:toDate:options: method.
If the string was originally created from an NSDate, then you'll want to use that original NSDate to compare against [NSDate date] using NSDate's compare: method (or some variant, such as earlierDate: or laterDate:).
You should use 24-hour based NSDateFormatter and compare as strings ("09:00am" > "08:00pm", but "09:00" < "20:00") . But in general it is right to operate with NSDate instances instead of strings