How in iOS to get first date of the month? [duplicate] - ios

This question already has an answer here:
NSDateFormatter - 1 day incorrect?
(1 answer)
Closed 7 years ago.
I try to get first date for the current month from [NSDate new]. My problem is that instead of 2015/06/01 I always receive 2015/05/31. I even try to convert string 20150601 to NSDate and I still receive 2015/05/31.
Here is my CODE (for the second element):
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"yyyyMMdd"];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
currentMonth = [dateFormatter dateFromString:#"20150601"];
The result is:
(lldb) print currentMonth
(__NSDate *) $0 = 0x79e64820 2015-05-31 21:00:00 UTC
EDIT:
Ok, I understand my mistake - I don't check correctly result of my operations. They always result in UTC.
10x, for answer and all comments. I will be more careful next time.

NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:today];
components.day = 1;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSTimeZone *zone = [NSTimeZone localTimeZone];
[formatter setTimeZone:zone];
[formatter setDateFormat:#"yyyyMMdd"];
NSDate *dayOneInCurrentMonth = [gregorian dateFromComponents:components];
NSString *currentMonth = [formatter stringFromDate:dayOneInCurrentMonth];
NSLog(#"%#",currentMonth);
Output
2015-06-08 14:07:30.924 NSDATEDemo[1943:39838] 20150601

Create NSDateComponents from [NSDate date], set the current day to 1 and re-create your NSDate object:
- (NSDate *) dateAtStartOfMonth
{
//Not tested!!!
NSDateComponents *comp = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]];
[comp setDay:1];
return [[NSCalendar currentCalendar] dateFromComponents:comp];
}

Related

NSDateComponents issue - set incorrect day [duplicate]

This question already has answers here:
Unexpected value from NSDate
(2 answers)
Closed 6 years ago.
There are many issues similar to mine, but something goes wrong. Why function setDay sets to 1 day less? Where did I go wrong?
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *today = [NSDate date];
NSLog(#"today date = %#", today);
NSDateComponents *components = [calendar components:(NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear ) fromDate:today];
[components setDay:1];
NSLog(#"modified date = %#", [calendar dateFromComponents:components]);
Log:
today date = 2016-07-04 10:01:30 +0000
modified date = 2016-06-30 21:00:00 +0000
Modified date should be 2016-07-01
Likely it is 2016-07-01, 24:00 GMT. NSLog() prints it out for GMT, not your locale time.
See here: Unexpected value from NSDate
You should add NSCalendarUnitHour in NSDateComponents like this then then you get correct date
NSDateComponents *components = [calendar components:(NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear |NSCalendarUnitHour) fromDate:today];
Try this code:
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setTimeZone:[NSTimeZone defaultTimeZone]]; // your time 00:00:00
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSLog(#"modified date = %#", [df stringFromDate:[calendar dateFromComponents:components]]); // Date format NSString

iOS set date to MM//DD/YY 00:00:00

I know there's a few questions already on this but I keep running into the same error regardless of what I do to my code. I am working in the simulator, I have location set to my long/lat. When I try to convert the current date to zero hours, minutes, seconds I always get this result:
2015-07-10 08:53:19.868 xxxxxxxxxxxxxxxxx[2184:7462272] Today at start of day:2015-07-10 04:00:00 +0000
Here's my code:
NSDate* today = [[NSDate alloc] init];
NSCalendar* currentCalendar = [NSCalendar currentCalendar];
NSDateComponents* dateComponents = [currentCalendar components:NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitYear fromDate:today];
NSInteger thisMonth = [dateComponents month];
NSInteger thisDay = [dateComponents day];
NSInteger thisYear = [dateComponents year];
NSDateComponents* dayComponents = [[NSDateComponents alloc] init];
[dayComponents setDay:thisDay];
[dayComponents setMonth:thisMonth];
[dayComponents setYear:thisYear];
NSDate* todayAtMidnight = [currentCalendar dateFromComponents:dayComponents];
NSLog(#"Today at start of day:%#", todayAtMidnight);
Even if add
[dayComponents setHour:0]; the hour still comes out as 4.
What am I doing wrong?
To get the beginning of today you can use
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:[NSDate date]];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSLog(#"date %#", [calendar dateFromComponents:components]);
Make sure you have the correct timezone
2015-07-10 04:00:00 +0000 is UTC, not your local timezone.
To display it in your local timezone, use an NSDateFormatter:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm";
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
NSLog([dateFormatter stringFromDate:todayAtMidnight]);
Use NSDateFormatter as follow because system timezone is UTC:
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate * curDate = [formatter dateFromString:[NSDate date]];
Then you'll get 2015-07-10 00:00:00.

Comparing NSDates Without Regard To Time [duplicate]

This question already has answers here:
Comparing two NSDates and ignoring the time component
(16 answers)
Closed 9 years ago.
Essentially I have a tip of the day feature, with specific tips associated with dates, and I need a way to compare the current NSDate to the saved date for the tip, regardless of time. Obviously the tip for January 1st is relevant at 10AM and 10:30, so I can't literally compare the NSDates. Here are some of the things I've tried:
Try 1 - Doesn't work
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
// [df setDateFormat:#"yyyy-MM-dd hh:mm:ss a"];
[df setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
Try 2 - Doesn't work
NSString * zoneString = [[NSString stringWithFormat:#"%i-%i-%iT00:00:00", year, month, day] substringFromIndex:([[NSString stringWithFormat:#"%i-%i-%iT00:00:00", year, month, day] length] - 5)];
NSTimeInterval timeInterval = [[zoneString substringToIndex:3] intValue] * 3600;
timeInterval += [[zoneString substringFromIndex:3] intValue] * 60;
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:timeInterval]];
[formatter setDateFormat:#"yyyy'-'MM'-'dd' 'HH':'mm':'ss ZZZ"];
NSLog(#"%#", [formatter stringFromDate:myDate]);
Try 3 - Doesn't work
NSDate *date = [NSDate date];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&date interval:NULL forDate:date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd"];
if ([[dateFormat stringFromDate:date] isEqualToString:[dateFormat stringFromDate:tipDate]])
As a rule of thumb, when you compare or manipulate NSDates, the right tool for the job is usually a combination of NSCalendar and NSDateComponents.
Use NSDateFormatter only when you need to format and display a NSDate.
With this in mind, NSDateComponents is the way to go, since you want to compare a subset of components from the two dates.
Create two NSDateComponents instances and compare them.
Example:
- (BOOL)isToday:(NSDate *)date {
NSDateComponents *todayComponents = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
fromDate:[NSDate date]];
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
fromDate:date];
return [dateComponents isEqual:todayComponents];
}

Constructing an NSDate from today's date and a string with the time

If I have a string representing a time, say "10:45 am", and do the following to parse the string:
NSDateFormatter *dateFormat;
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"h:mm a"];
NSLog(#"%#", [dateFormat dateFromString:#"10:45 AM"]);
I would get this logged:
2013-09-09 17:52:30.416 TimeTest[49491:a0b] 2000-01-01 15:45:00 +0000
How can I create an NSDate for the current day at the given time? I tried this
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"h:mm a"];
NSDate *time = [formatter dateFromString:#"10:45 AM"];
NSDateComponents *timeComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit ) fromDate:time];
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];
NSDateComponents *newComponents = [[NSDateComponents alloc]init];
newComponents.timeZone = [NSTimeZone systemTimeZone];
[newComponents setDay:[dateComponents year]];
[newComponents setMonth:[dateComponents month]];
[newComponents setYear:[dateComponents year]];
[newComponents setHour:[timeComponents hour]];
[newComponents setMinute:[timeComponents minute]];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *combinedDate = [gregorianCalendar dateFromComponents:newComponents];
NSLog(#"%#", combinedDate);
with the result
2013-09-09 19:57:14.506 TimeTest[49712:a0b] 2019-03-06 15:45:00 +0000
How should I go about this?
I'm not exactly sure what you are looking for. For what I understand, you want to build a date with the current year, month and day, but with your supplied time by parsing it from a string.
If that is the case, as others have pointed out, you need to play with NSDateComponents.
Based on your code I wrote these lines. They should build a date by merging two dates. The current one and the one you parsed.
// Get the full current date
NSDate *date = [NSDate date];
// Get the current calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
// Split the date into components but only take the year, month and day and leave the rest behind
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];
// Build the date formatter
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"h:mm a"];
// Convert the string time into an NSDate
NSDate *time = [formatter dateFromString:#"10:45 AM"];
// Split this one in components as well but take the time part this time
NSDateComponents *timeComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit ) fromDate:time];
// Do some merging between the two date components
dateComponents.hour = timeComponents.hour;
dateComponents.minute = timeComponents.minute;
// Extract the NSDate object again
NSDate *result = [calendar dateFromComponents:dateComponents];
// Check if this was what you where looking for
NSLog(#"%#",result);
Please be aware that this sample code is by far non-optimized. There are more crisp ways to obtain what you are looking for by using time intervals, but I felt like you wanted a dirty simple example on how to do components copy and paste and then extracting dates.
This will create a date for the beginning of the day in the current time zone.
NSDate *today = [NSDate date];
NSTimeInterval interval;
NSCalendar *cal = [NSCalendar currentCalendar];
[cal rangeOfUnit:NSDayCalendarUnit
startDate:&today
interval:&interval
forDate:today];
Now we add the time:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// I have to set the locale to posix_en_us, as my system is using 24hour style as default
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[dateFormatter setDateFormat:#"hh:mm a"];
NSDate *time = [dateFormatter dateFromString:#"10:45 AM"];
NSDateComponents *comps = [cal components:(NSHourCalendarUnit | NSMinuteCalendarUnit)
fromDate:time];
NSDate *dateAndTime = [cal dateByAddingComponents:comps
toDate:today
options:0];
dateAndTime will now be todays date with 10:45 am in the local timezone.
controlling in the debugger:
po dateAndTime
$0 = 0x41b7df138c00000d 2013-09-10 08:45:00 +0000
This is correct, as my timezone is 2 hours ahead to GMT, as we still have summer time.

UITableview title bar with date for week?

How can I have the title of UITableview with date?
I know I can edit the title using:
self.title=#"meals for ..";
I want to add the date for one week. How can I do that?
You can get a date like this:
NSDate *theDateToday = [NSDate date];
And format it like this:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEE MMM dd"];
NSString *theDateAsAString = [dateFormatter stringFromDate:theDateToday];
Combine that with what you have like this:
self.title = [NSString stringWithFormat:#"meals for %#", theDateAsAString];
As for finding the days of the week, you could try adapting this answer.
- (NSString *)getWeekStartDateAsString:(NSDate *)date {
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];
int dayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:today] weekday];// this will give you current day of week
[components setDay:([components day] - ((dayofweek) - 2))];// for beginning of the week.
NSDate *beginningOfWeek = [gregorian dateFromComponents:components];
NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init];
[dateFormat_first setDateFormat:#"yyyy-MM-dd"];
dateString2Prev = [dateFormat stringFromDate:beginningOfWeek];
weekstartPrev = [[dateFormat_first dateFromString:dateString2Prev] retain];
return weekstartPrev;
}
- (NSString *)getWeekEndDateAsString:(NSDate *)date {
NSCalendar *gregorianEnd = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsEnd = [gregorianEnd components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];
int Enddayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:today] weekday];// this will give you current day of week
[componentsEnd setDay:([componentsEnd day]+(7-Enddayofweek)+1)];// for end day of the week
NSDate *EndOfWeek = [gregorianEnd dateFromComponents:componentsEnd];
NSDateFormatter *dateFormat_End = [[NSDateFormatter alloc] init];
[dateFormat_End setDateFormat:#"yyyy-MM-dd"];
dateEndPrev = [dateFormat stringFromDate:EndOfWeek];
weekEndPrev = [[dateFormat_End dateFromString:dateEndPrev] retain];
return weekEndPrev;
}
You end result might look like this:
self.title = [NSString stringWithFormat:#"meals for %#-%#", [self getWeekStartDateAsString:theDateToday], [self getWeekEndDateAsString:theDateToday]];
A rarely known NSCalendar method will be the best option IMO
rangeOfUnit:startDate:interval:forDate:. It gives you the start and the duration (interval) for a certain time unit. With it it is easy to find the start of the week in the used calendar and add the range-1 to get the latest second in that week.
With the also rarely seen localizedStringFromDate:dateStyle:timeStyle: Available in OS X v10.6, iOS 4.0 it is easy to create a localized representation of the dates.
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDate *startOfTheWeek;
NSDate *endOfWeek;
NSTimeInterval interval;
[cal rangeOfUnit:NSWeekCalendarUnit
startDate:&startOfTheWeek
interval:&interval
forDate:now];
//startOfWeek is 2013-06-02 22:00:00 +0000 now (note: it is GMT with timezone support for my timezone Europe/Berlin/DST)
endOfWeek = [startOfTheWeek dateByAddingTimeInterval:interval-1];
// 2013-06-09 21:59:59 +0000
NSString *text = [NSDateFormatter localizedStringFromDate:startOfTheWeek
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterNoStyle];
text = [text stringByAppendingString:#" to "];
text = [text stringByAppendingFormat:#"%#", [NSDateFormatter localizedStringFromDate:endOfWeek
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterNoStyle]];
self.title=text;
results in 03.06.13 to 09.06.13 for my german locale, where Monday is start of the week.

Resources