Convert week number for a certain year to a month name - ios

After searching through SO but apart from this question I found no solutions. I'm thinking about creating a method that would accept the int of the week number and the int of the year and that would return an NSString with the name of the month:
- (NSString *)getMonthNameFromNumber:(int)weekNumber andYear:(int)year
But I can't find a way to approach this problem. Would be glad if anyone could help with advices.

Something like this will do
- (NSString *)monthNameForWeek:(NSUInteger)week inYear:(NSInteger)year {
NSDateComponents * dateComponents = [NSDateComponents new];
dateComponents.year = year;
dateComponents.weekOfYear = week;
dateComponents.weekday = 1; // 1 indicates the first day of the week, which depends on the calendar
NSDate * date = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM"];
return [formatter stringFromDate:date];
}
Note that this is dependent on the current calendar set in the device preferences.
In case this doesn't fit your needs, you can provide a NSCalendar instance and use it to retrieve the date instead of using currentCalendar. By doing so you can configure things like which is the first day of the week and so on. The documentation of NSCalendar is worth a read.
If using a custom calendar is a common case, just change the implementation to something like
- (NSString *)monthNameForWeek:(NSUInteger)week inYear:(NSInteger)year {
[self monthNameForWeek:week inYear:year calendar:[NSCalendar currentCalendar]];
}
- (NSString *)monthNameForWeek:(NSUInteger)week inYear:(NSInteger)year calendar:(NSCalendar *)calendar {
NSDateComponents * dateComponents = [NSDateComponents new];
dateComponents.year = year;
dateComponents.weekOfYear = week;
dateComponents.weekday = 1; // 1 indicates the first day of the week, which depends on the calendar
NSDate * date = [calendar dateFromComponents:dateComponents];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM"];
return [formatter stringFromDate:date];
}
As an unrelated side note, you should avoid get for methods names, unless you are returning a value indirectly.

With anything to do with dates, you need to involve a calendar. Your question assumes the Gregorian Calendar, but I suggest you change your method declaration to:
- (NSString*)monthNameFromWeek:(NSInteger)week year:(NSInteger)year calendar:(NSCalendar*)cal;
From this, there is also the ambiguity of which day we're talking about. For example (this hasn't been checked), week 4 of 2015 may contain both January and February. Which one is correct? For this example, we'll use a weekday of 1, which indicates Sunday (in the UK Gregorian Calendar), and we'll use whatever month this falls in to.
As such, your code would be:
// Set up our date components
NSDateComponents* comp = [[NSDateComponents alloc] init];
comp.year = year;
comp.weekOfYear = week;
comp.weekday = 1;
// Construct a date from components made, using the calendar
NSDate* date = [cal dateFromComponents:comp];
// Create the month string
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMMM"];
return [dateFormatter stringFromDate:date];

Related

How to add Date if today is last day of the month.?

I am stuck a problem where i need to create a stepper by 7 day. I code for that but in case of last days of month it will remain continue with same month rather than it should be change in next month as well.
Same case needs to be implemented for the year.
For e.g if today is 30 dec 2016 then by adding 7 day it needs to be change as 7 jan 2017. Thanks in advance.
Try this. Here I have added 7 days from a particular date.
// Enter current date
NSString *currentDate = #"2016-12-30";
// Set number of days to add
int addDaysCount = 7;
// Set date formatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
// Convert string to NSDate
NSDate *dateFromString = [dateFormatter dateFromString:currentDate];
// Initialize date component
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setDay:addDaysCount];
// Retrieve date with increased days count
NSDate *newDate = [[NSCalendar currentCalendar]
dateByAddingComponents:dateComponents
toDate:dateFromString options:0];
NSLog(#"Current date: %#", [dateFormatter stringFromDate:dateFromString]);
NSLog(#"Updated date: %#", [dateFormatter stringFromDate:newDate]);
NSDate *now = [NSDate date];
NSDate *sevenDaysAgo = [now dateByAddingTimeInterval:+7*24*60*60];
Here add 7 days add to your current date

NSDate - Adding Days doesn't change year value

I have a Label which i want to hold a specific date. The initial date should be the current Date, and the user should be able to step through the time by the interval of a day. After a little research, I found out, that it would be best to set NSDateComponents and add them to the current Date.
My problem is as following: When I step through the time, everything seems fine, until i reach the end/beginning of a year. For instance, the date hold in the label is the 01.01.2014, when I tap the "previousDayButton" it would become 31.12.2014. I thought about asking for the date and then setting the year manually, but I can't possibly think of THAT to be the solution.
So here is my Code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setupInterface];
}
- (void)setupInterface{
orderDate = [NSDate date];
[self updateDateLbl];
}
- (void)updateDateLbl{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd.MM.YYYY"];
dateLbl.text = [dateFormatter stringFromDate:orderDate];
}
- (IBAction)nextDay:(id)sender {
NSDateComponents *comps = [[NSDateComponents alloc]init];
comps.day = 1;
orderDate = [[NSCalendar currentCalendar] dateByAddingComponents:comps toDate:orderDate options:0];
[self updateDateLbl];
}
- (IBAction)previousDay:(id)sender {
NSDateComponents *comps = [[NSDateComponents alloc]init];
comps.day = -1;
orderDate = [[NSCalendar currentCalendar] dateByAddingComponents:comps toDate:orderDate options:0];
[self updateDateLbl];
}
I would love some help :)
Use Xcode help for NSDateFormatter. From the documentation:
It uses yyyy to specify the year component. A common mistake is to use YYYY. yyyy specifies the calendar year whereas YYYY specifies the year (of “Week of Year”), used in the ISO year-week calendar. In most cases, yyyy and YYYY yield the same number, however they may be different. Typically you should use the calendar year.
2014 started on a Wednesday. Tuesday, 31st Dec. 2013, is in the same week - week 1 of 2014. That's what YYYY displays. yyyy displays 2013.

NSDate delay date change

This is probably a simple solution but does anyone know how to delay the NSDate change past midnight? Any insight would be really helpful, thanks!
Edit:
I am currently getting the date this way and displaying a locations data based on that day. But, much like the NSDate is logically supposed to work, it switches to the next day at midnight. I want the date to change at 3am instead of at 12am.
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"EEEE"];
today = [f stringFromDate:[NSDate date]];
Should I just use the time instead of using NSDate? I am a bit of a noob to iOS so any insight would be helpful. Thanks for your responses already.
I must admit that I do not yet understand why you want to display a "wrong" weekday
name, but the following code should do what you want. This is only one of various ways
to achieve your task.
Convert date to "date components:"
NSCalendar *cal = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit;
NSDateComponents *comp = [cal components:unitFlags fromDate:[NSDate date]];
Subtract one day if necessary:
if (comp.hour < 3) {
comp.day -= 1;
}
Convert adjusted components back to date:
NSDate *adjustedDate = [cal dateFromComponents:comp];
Your original code, now using the adjusted date:
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"EEEE"];
NSString *today = [f stringFromDate:adjustedDate];

Weekday of first day of month

I need to get the weekday of the first day of the month. For example, for the current month September 2013 the first day falls on Sunday.
At first, get the first day of current month (for example):
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:today];
components.day = 1;
NSDate *firstDayOfMonth = [gregorian dateFromComponents:components];
Then use NSDateFormatter to print it as a weekday:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEEE"];
NSLog(#"%#", [dateFormatter stringFromDate:firstDayOfMonth]);
P.S. also take a look at Date Format Patterns
Here is the solution to getting the weekday name of the first day in the current month
NSDateComponents *weekdayComps = [[NSDateComponents alloc] init];
weekdayComps = [calendar.currentCalendar components:calendar.unitFlags fromDate:calendar.today];
weekdayComps.day = 1;
NSDateFormatter *weekDayFormatter = [[NSDateFormatter alloc]init];
[weekDayFormatter setDateFormat:#"EEEE"];
NSString *firstweekday = [weekDayFormatter stringFromDate:[calendar.currentCalendar dateFromComponents:weekdayComps]];
NSLog(#"FIRST WEEKDAY: %#", firstweekday);
For the weekday index, use this
NSDate *weekDate = [calendar.currentCalendar dateFromComponents:weekdayComps];
NSDateComponents *components = [calendar.currentCalendar components: NSWeekdayCalendarUnit fromDate: weekDate];
NSUInteger weekdayIndex = [components weekday];
NSLog(#"WEEKDAY INDEX %i", weekdayIndex);
You can also increment or decrement the month if needed.
Depending on the output you need you may use NSDateFormatter (as it was already said) or you may use NSDateComponents class. NSDateFormatter will give you a string representation, NSDateComponents will give you integer values. Method weekday may do what you want.
NSDateComponents *components = ...;
NSInteger val = [components weekday];
For Swift 4.2
First:
extension Calendar {
func startOfMonth(_ date: Date) -> Date {
return self.date(from: self.dateComponents([.year, .month], from: date))!
}
}
Second:
self.firstWeekDay = calendar.component(.weekday, from: calendar.startOfMonth(Date()))

iPhone OS: How do I create an NSDate for a specific date?

Seems like a simple thing but I can't seem to find a way to do it.
It would be great to see a couple different methods.
#Chuck's answer is correct, and lead me to the following code. Thought I'd share:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:10];
[comps setMonth:10];
[comps setYear:2010];
NSDate *date = [[NSCalendar currentCalendar] dateFromComponents:comps];
You can use this
NSString *dateString = #"03-Sep-11";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"dd-MMM-yy";
NSDate *date = [dateFormatter dateFromString:dateString];
Hope this will help you out.
If you're talking about a specific calendar date rather than a UNIXy date, you probably want NSCalendar's dateFromComponents:.
Swift Examples
Examples are often the easiest way to learn. Here are a few examples.
Now
This one is the easiest.
let currentDateTime = Date()
February 20, 2017
// Specify date components
var dateComponents = DateComponents()
dateComponents.year = 2017
dateComponents.month = 2
dateComponents.day = 20
// Create date from components
let userCalendar = Calendar.current // user calendar
let dateThisPostWasUpdated = userCalendar.date(from: dateComponents)
April 1, 1976
// Specify date components
var dateComponents = DateComponents()
dateComponents.year = 1976
dateComponents.month = 4
dateComponents.day = 1
// Create date from components
let userCalendar = Calendar.current // user calendar
let appleFoundedDate = userCalendar.date(from: dateComponents)
Need more details...?
There are other ways to create dates, too. If you want to learn those, as well as how to display a date, then see my fuller answer.
See the documentation for NSDate. You can use the dateFromString: method of NSDateFormatter or the dateFromComponents: method of NSCalendar.
I found this thread while looking for an answer to this question but then I found a good example in one my Big Nerd Ranch Objective-C Programming book. Credit to them, not me.
NSDateComponents *myBDay =[[NSDateComponents alloc] init];
[myBDay setDay:22];
[myBDay setMonth: 04];
[myBDay setYear: 1984];
[myBDay setHour:9];
[myBDay setMinute:25];
[myBDay setSecond:35];
NSCalendar *g = [[ NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *dateOfBirth = [g dateFromComponents:myBDay];
It is ridiculous, isn't it ?
Mid-2013 and Apple still hasn't provided a simple way to set a NSDate value.
During my current iPad project, I couldn't believe I had to stop productivity for a while to write my own helper class to get the Year value from an NSDate. I mean, come on, this is basic stuff.
Anyway, here's the helper class I used in my project, to convert a string into an NSDate value :
#implementation DateHelper
+(NSDate*)parseDateString:(NSString *)dateString
{
NSDateFormatter *rfc3339TimestampFormatterWithTimeZone = [[NSDateFormatter alloc] init];
[rfc3339TimestampFormatterWithTimeZone setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
[rfc3339TimestampFormatterWithTimeZone setDateFormat:#"MMM dd, yyyy"];
NSDate *theDate = nil;
NSError *error = nil;
if (![rfc3339TimestampFormatterWithTimeZone getObjectValue:&theDate forString:dateString range:nil error:&error]) {
NSLog(#"Date '%#' could not be parsed: %#", dateString, error);
}
return theDate;
}
#end
Using this code, you could set an NSDate value using something like:
NSDate* date = [DateHelper parseDateString:#"Jul 16, 2013"];
Note: this function was based on code taken from here:
https://stackoverflow.com/a/3968411/391605
My solution had been to use the following code, but I found that sometimes, it just wouldn't parse, and would return nil.
// Take a date string in the format "Oct 23, 2013", and convert it into a NSDate value
// THIS DOESN'T WORK ! DON'T TRUST THIS CODE !!
NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM dd, yyyy"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate* date = [formatter dateFromString:dateString];
I remember it failed miserably on "Oct 12, 2012"... which is why I gave up and used the more complicated "parseDateString" function shown above.
My point is... be careful.
Some of the very-basic NSDate functions just don't work properly...

Resources