Getting date of week of year - ios

I want to get start date of week from its number with following code:
+ (NSDate *)dateOfWeek:(NSInteger)weekOfYear year:(NSInteger)year {
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setFirstWeekday:2]; // monday
calendar.minimumDaysInFirstWeek = 4; // iso 8601
NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = year;
components.weekOfYear = weekOfYear;
[components setWeekday:2]; // monday
NSDate *date = [calendar dateFromComponents:components];
return date;
}
If year = 2017 and weekOfYear = 52 (or other valid numbers) date is correct:
2017-12-24 21:00:00 +0000
if year = 2018 and weekOfYear = 2 date is correct too:
2018-01-07 21:00:00 +0000
but if year = 2018 and weekOfYear = 1 date is incorrect:
2018-12-30 21:00:00 +0000
it must be 2017-12-31 21:00:00 +0000.
There is a second way to get dates using NSDateFormatter:
NSString *dateString = [NSString stringWithFormat:#"%li %li", (long)year, (long)weekOfYear];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy ww";
NSDate *date = [dateFormatter dateFromString:dateString];
NSLog(#"%#", [date description]);
But it works with the same problems with year = 2018 and weekOfYear = 1!
What I`m doing wrong with getting week dates or this is Foundation bug?

It's not a Foundation bug.
You need the component yearForWeekOfYear to get the correct week of year:
components.yearForWeekOfYear = year;
The date formatter issue is actually the same, the yearForWeekOfYear specifier is Y
dateFormatter.dateFormat = #"YYYY ww";

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

a date string without year to NSDate with year

I have a date string of
"5:09 pm Wed Sep 2",which is coming from server.
when converting the string into NSDate.
"2000-09-02 17:09:00 +0000" but the year should have been "2015" like:
"2015-09-02 17:09:00 +0000"
Here is my code please let me know where is the problem
NSString *dateStr = #"5:09 pm Wed Sep 2";
// Convert string to date object
NSString *dateFormat= ([self hasAMPM])?#"hh:mm a EEEE MMM d":#"hh:mm a EEEE MMM d" ;
NSDate * date = [self toLocalTime:[self convertDateFromString:dateStr OutputFormat:dateFormat]];
///****
-(BOOL)hasAMPM{
NSString *formatStringForHours = [NSDateFormatter dateFormatFromTemplate:#"j" options:0 locale:[NSLocale currentLocale]];
NSRange containsA = [formatStringForHours rangeOfString:#"a"];
BOOL hasAMPM = containsA.location != NSNotFound;
return hasAMPM;
}
-(NSDate *)toLocalTime:(NSDate *)date
{
NSTimeZone *tz = [NSTimeZone systemTimeZone];
NSInteger seconds = [tz secondsFromGMTForDate: date];
return [NSDate dateWithTimeInterval: seconds sinceDate: date];
}
-(NSDate *)convertDateFromString:(NSString *)strDate OutputFormat:(NSString *)outPutFormat
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:outPutFormat];
NSDate *date1= [formatter dateFromString:strDate];
return date1;
}
Please help me to get out of this situation.
If you want to add the year in your date according to current date, this works for dates from 1970 onwards, haven't checked for beyond that:
NSString *dateStr = #"5:09 pm Wed Sep 2";
NSString *dateString = [dateStr stringByAppendingString:#" 1970"];
// Convert string to date object
NSString *dateFormat= ([self hasAMPM])?#"hh:mm a EE MMM d yyyy":#"hh:mm a EE MMM d yyyy" ;
NSDate * date = [self toLocalTime:[self convertDateFromString:dateString OutputFormat:dateFormat]];
NSCalendar *greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
greCalendar.timeZone = [NSTimeZone systemTimeZone];
NSDateComponents *componenetsForCurrent = [greCalendar componentsInTimeZone:[NSTimeZone systemTimeZone] fromDate:[NSDate date]];
NSInteger year = componenetsForCurrent.year;
NSDate *requiredDate = [greCalendar dateByAddingUnit:NSCalendarUnitYear value:(year-1970) toDate:date options:NSCalendarWrapComponents];
You can split your date using NSDateComponents, and work with year independently
NSDateComponents *dateComponents = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:date];
[dateComponents setYear:someYear];
date = [calendar dateFromComponents:dateComponents];

Adding an amount of hours to NSDate isn't working?

I've spent a good few hours trying to make this work. Here's what I'm trying to do:
Take input from a UITextField in the form HH:mm AM/PM
Convert that string into an NSDate object, and update the month/day/year properties of that NSDate to reflect the curren month/day/year.
Add 4 hours to the time of the NSDate object.
That last bit isn't working. It works for times such as 12:00 PM and 12:30 PM but for times such as 2:30 PM, it will output 4:30 PM rather than 6:30 PM as expected. Here is my code, broken up to reflect those three tasks.
Task 1 - checking to see if the text input was HH:mm AM/PM
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
[format setTimeZone:[NSTimeZone systemTimeZone]];
[format setDateFormat:#"HH:mm a"];
NSString *dateString = textField.text;
NSLog(#"input datestring: %#", dateString);
NSDate *parsed = [format dateFromString:dateString];
if (parsed) {
NSLog(#"datestring is valid, %#", parsed);
}
Task 2- Updating the m/d/y components of that date to reflect today's.
//gregorian calendar, get the hour and minute components from the input time
NSCalendar *greg = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [greg components: NSCalendarUnitHour | NSCalendarUnitMinute fromDate:parsed];
//get the month/day/year components from the current date
NSDateComponents *comps = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
//set the components of the original date to the month/day/year components of today
[components setYear:comps.year];
[components setDay:comps.day];
[components setMonth:comps.month];
//create the new date.
NSDate* newDate = [greg dateFromComponents:components];
NSLog(#"########### %#", newDate);
Task 3 - Add 4 hours.
int hours = 4 ;
NSString *output;
NSDateComponents *add = [[NSDateComponents alloc] init];
[add setHour:hours];
newDate = [greg dateByAddingComponents:add toDate:newDate options:0];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateStyle:NSDateFormatterShortStyle];
[df setTimeStyle:NSDateFormatterShortStyle];
output = [df stringFromDate:newDate];
NSLog(#"new date: %#", output);
Log:
2015-08-27 16:03:35.672 Del Taco[1960:117431] input datestring: 2:30 pm
2015-08-27 16:03:35.673 Del Taco[1960:117431] datestring is valid, 2000-01-01 20:30:00 +0000
2015-08-27 16:03:35.673 Del Taco[1960:117431] ########### 2015-08-27 19:30:00 +0000
2015-08-27 16:03:35.674 Del Taco[1960:117431] new date: 8/27/15, 4:30 PM
I think I have this figured out. It was my date formatter where I set the format like this:
#"HH:mm a"
I went to Unicode's website to double check that I was doing this right, and ended up changing my format string to:
#"h:mm a"
And things seem to be working out well!

NSCalendar set firstWeekDay to monday but results are different

I am trying to get the beginning date of a month.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"begining of month: %# from today", [self beginningOfMonth:[NSDate date]]);
}
- (NSDate *)beginningOfMonth:(NSDate *)date {
NSCalendar *calendar = [NSCalendar currentCalendar];
calendar.locale = [NSLocale currentLocale];
calendar.timeZone = [NSTimeZone defaultTimeZone];
calendar.firstWeekday = 2;
NSDateComponents *componentsCurrentDate = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday|NSCalendarUnitWeekOfMonth fromDate:date];
NSDateComponents *componentsNewDate = [NSDateComponents new];
componentsNewDate.year = componentsCurrentDate.year;
componentsNewDate.month = componentsCurrentDate.month;
componentsNewDate.weekOfMonth = 1;
componentsNewDate.weekday = calendar.firstWeekday;
return [calendar dateFromComponents:componentsNewDate];
}
But the console outputs is 2015-06-05 10:41:54.544 Test[1119:25066] begining of month: 2015-05-31 16:00:00 +0000
I just looked the calendar, it should be 2015-06-01 but it shows 2015-05-31. And I did set firstWeekday to 2, so it's Monday.
It seems you are getting the right result. Depending on the time zone of your Xcode installation, the console will output a different date.
Try using a date formatter in NSLog.
NSDateFormatter *f = [[NSDateFormatter alloc] init];
NSDate *firstMonday = [self beginningOfMonth:[NSDate date];
NSLog(#"First Monday of month: %#", [f stringFromDate:firstMonday]);

NSDate Showing Wrong Day

I am taking an NSDate, and pulling just a 2-digit number, representing the day of the month into an NSString. One of the dates in question is:
2013-11-30 00:00:00 +0000
I use:
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:#"dd"];
NSString *datefromdate = [formatter2 stringFromDate:articleDate];
NSLog(#"Date%#", datefromdate);
[formatter2 release];
but the log comes back
29
You are probably in a negative time zone i.e. GMT minus something. This is why 2013-11-30 00:00:00 +0000 GMT is on the 29th day when you log it. Set the formatter to GMT and you will be fine.
Set the timezone you want the time date formatter to use. NSDate is the first instant of 1 January 2001, GMT and thus has no timezone information in it.
So, this, according to Apple, is going to get complicated needing up to five classes: NSDateFormatter, NSDate, NSCalendar, NSTimeZone and finally NSDateComponents.
If all you want is the day you can use NSDateComponents.
Example:
NSString *dateString = #"2013-11-30 00:00:00 +0000";
NSDateFormatter *inDateFormatter = [[NSDateFormatter alloc] init];
[inDateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss Z"];
NSDate *date = [inDateFormatter dateFromString:dateString];
NSLog(#"dateFromString: %#", date);
NSTimeZone *timezone = [NSTimeZone timeZoneForSecondsFromGMT:0];
// Using date formatter, result is a string
NSDateFormatter *outDateFormatter = [NSDateFormatter new];
[outDateFormatter setTimeZone:timezone];
[outDateFormatter setDateFormat:#"dd"];
NSString *dayString = [outDateFormatter stringFromDate:date];
NSLog(#"date formatter day: %#", dayString);
// Using date components, result is an integer
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone: timezone];
NSDateComponents *dateComponents = [calendar components:NSDayCalendarUnit fromDate:date];
NSInteger day = [dateComponents day];
NSLog(#"date components day: %i", day);
NSLog output:
dateFromString: 2013-11-30 00:00:00 +0000
date formatter day: 30
date components day: 30

Resources