iOS: Value of NSCalendarUnitWeekday is 1 for a Monday - ios

I am trying to parse out the day of the week given a NSDate.
NSDateComponents *comps = [[NSDateComponents alloc] init];
comps=[calendar components: NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitWeekOfMonth | NSCalendarUnitWeekOfYear | NSCalendarUnitWeekday fromDate:date];
When the value of date is 2015-11-30 00:58:52 +0000 (this is Monday), the value of comps.weekday is printed out as 1
When the value of date as 2015-11-15 09:59:46 +0000 (this is Sunday), the value of comps.weekday is also 1.

NSDateComponents uses the timezone of the NSCalendar to interpret the current day. NSCalendar defaults to the using the timezone of the device.
2015-11-30 00:58:52 UTC is only a Monday if you are in the UTC timezone, or one of the later ones. If you are in the EST (-5) timezone, then this would be a Sunday.
If you want to interpret the day of week at the UTC timezone then change the timeZone property to [NSTimezone timeZoneForSecondsFromGMT:0].
Documentation ref: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/#//apple_ref/occ/instp/NSDateComponents/timeZone

Related

Calculate duration between two dates(finding upcoming/old birthdays) in ios [duplicate]

This question already has answers here:
Number of days between two NSDates [duplicate]
(16 answers)
Closed 6 years ago.
How can i calculate duration between two dates. like
I am getting contacts birthday list from contacts framework. Now i want to compare Today date with user DOB value and i should display the "remaining days count"(birthday).
For Example:
In contacts i added one user like: DOB: dd/MM/yyyy -->12/04/1960
now today date is: 25/04/2016
I want to get the upcoming birthday date(duration between two dates)
o/p: 18 days
How can i get this
Try below line of code. you will get the solution.
NSDateComponents *components;
NSInteger days;
components = [[NSCalendar currentCalendar] components: NSDayCalendarUnit
fromDate: startDate toDate: endDate options: 0];
days = [components day];
Use the following
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *conversionInfo = [currCalendar components:unitFlags fromDate:fistDate toDate:secondDate options:0];
int months = [conversionInfo month]; // to get number of months
int days = [conversionInfo day]; // to get number of days
int hours = [conversionInfo hour]; // to get hour difference
int minutes = [conversionInfo minute]; // to get hour difference
copied from Difference between two NSDates

Get NSDate from start of 7 days ago

I'm trying to do some simple 7 day history plotting. Given the current NSDate.date, I want to get the NSDate that corresponds to the start of day, 7 days ago. So basically 7 days prior to 0.00 this morning.
What I've tried, is the following:
// decompose the current date, do I need more component fields?
NSDateComponents *comps = [NSCalendar.currentCalendar components: NSDayCalendarUnit fromDate: NSDate.date];
NSLog(#"components: %#", comps);
// Back day up 7 days. Will this wrap appropriate across month/year boundaries?
comps.day -= 7;
NSDate *origin = comps.date;
NSLog(#"new date: %#", origin);
What I assumed was that by just specifying NSDayCalendarUnit, the other things would be defaults (like start of day, etc). Unfortunately, origin ends up as (null). What is the correct way to do this?
To construct a new date you should know not only a day but also a month and a year. So you should add NSYearCalendarUnit | NSMonthCalendarUnit. Also you should setup calendar and probably timezone properties of NSDateComponents's instance:
NSDateComponents *comps = [NSCalendar.currentCalendar components: NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate: NSDate.date];
comps.calendar = NSCalendar.currentCalendar;
comps.timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
NSLog(#"components: %#", comps);
// Back day up 7 days. Will this wrap appropriate across month/year boundaries?
comps.day -= 7;
NSDate *origin = comps.date;
NSLog(#"new date: %#", origin);

Convert month int value to formatted string

I want to use the "LLL" string format of NSDateFormatter to get the proper string for the month name: Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec
All I have is the integer value of the month. For example, if the value is 5, then I need an output string of "May".
I don't want to use a switch. Is there any way I can use NSDateFormatter and apply setDateFormat: with "LLL" ?
A better way to do this is to get the monthSymbols array from your formatter and index into that:
NSString * monthName = [formatter monthSymbols][monthInt];
If you want a date, though, NSCalendar and NSDateComponents will get you there, letting you create an NSDate from whatever date elements you have.
NSCalendar * cal = [NSCalendar currentCalendar];
NSDateComponents * comps = [NSDateComponents new];
[comps setMonth:monthVal];
NSDate * monthOnlyDate = [cal dateFromComponents:comps];
Now you can use your formatter on the date.
(Note that this date is basically meaningless aside from its use for this particular purpose; any unset properties -- hours, day, year -- of the components will be undefined, and the calendar will use its own choice of defaults for their values.)

How to show date with timezone for date, relevantly to defined country/zone?

I need to show a date in concrete time zone including DST (European time). App will be used in Lithuania, so time zone is +3 at summer and +2 at other time. The thing is, I have just a list of dates and I don't know how to show +3 for summer dates and +2 for other dates. Currently, I have time zones:
// Eastern European Summer Time UTC + 3 hours
NSTimeZone *timeZoneWithDst = [NSTimeZone timeZoneWithAbbreviation:#"EEST"];
//Eastern European Time UTC + 2 hours
NSTimeZone *timeZoneWithoutDst = [NSTimeZone timeZoneWithAbbreviation:#"EET"];
But how to loop through my list of dates and calculate should I add +3 or +2 to date?
UPDATE Finally I got it working by applying Martin R. suggestion to use time zone by name, not by abbreviation. In this way, date with this time zone handles DST automatically. Here's my code for converting dates:
NSTimeZone *TimeZone = [NSTimeZone timeZoneWithName:#"Europe/Vilnius"];
NSInteger seconds = [myTimeZone secondsFromGMTForDate:someDate];
NSDate *result = [NSDate dateWithTimeInterval:seconds sinceDate:someDate];
To convert an NSDate to a string representation, use NSDateFormatter. By default, it uses the local time zone. To display the date according to a concrete time zone, you can set
NSTimeZone *tz = [NSTimeZone timeZoneWithName:#"Europe/Vilnius"];
[dateFormatter setTimeZone:tz];
(According to http://www.timezoneconverter.com/cgi-bin/findzone, the time zone for Lithuania is "Europe/Vilnius".)
This is a very similar alternative that worked for me, in Swift:
var currentDate: NSDate {
let currentLocalTime = NSDate()
let localTimeZone = NSTimeZone.systemTimeZone()
let secondsFromGTM = NSTimeInterval.init(localTimeZone.secondsFromGMT)
let resultDate = NSDate(timeInterval: secondsFromGTM, sinceDate: currentLocalTime)
return resultDate
}

[NSCFString timeIntervalSinceReferenceDate]: unrecognized selector sent to instance

I would like to compare difference between two dates, but with the code below I got the error "[NSCFString timeIntervalSinceReferenceDate]: unrecognized selector sent to instance." What's wrong with the code?
NSDate *dateAdded=[eventDictionary objectForKey:#"dateAdded"];
NSDate *validUntilDate=[eventDictionary objectForKey:#"validUntilDate"];
NSDateComponents *sometimeAgo = [[NSCalendar currentCalendar] components:(NSSecondCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:dateAdded toDate:validUntilDate options:0];
It looks like dateAdded and/or validUntilDate are actually strings and not dates. Maybe they are strings representing dates, but strings after all.
You need to use an NSDateFormatter to convert your date strings to actual NSDates.

Resources