Get firstdate, lastdate of month? - ios

I want to get firstdate、lastdate of month,I try
NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
[components setDay:1];
self.currentDate = [calendar dateFromComponents:components];
int m = components.month;
int y = components.year;
int d = components.day;
log: 2012,5,1
How can i get lastdate od month?
please give me some advice,thank you!!

Some NSDate category methods I wrote will help you:
Here's an easy way to find the start of a month:
(NSDate *) startOfMonth
{
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDateComponents * currentDateComponents = [calendar components: NSYearCalendarUnit | NSMonthCalendarUnit fromDate: self];
NSDate * startOfMonth = [calendar dateFromComponents: currentDateComponents];
return startOfMonth;
}
All it does is take the year and month components from the current day, then convert back to a date again.
For the end of the month, I use a couple of methods:
- (NSDate *) dateByAddingMonths: (NSInteger) monthsToAdd
{
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDateComponents * months = [[NSDateComponents alloc] init];
[months setMonth: monthsToAdd];
return [calendar dateByAddingComponents: months toDate: self options: 0];
}
and
- (NSDate *) endOfMonth
{
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDate * plusOneMonthDate = [self dateByAddingMonths: 1];
NSDateComponents * plusOneMonthDateComponents = [calendar components: NSYearCalendarUnit | NSMonthCalendarUnit fromDate: plusOneMonthDate];
NSDate * endOfMonth = [[calendar dateFromComponents: plusOneMonthDateComponents] dateByAddingTimeInterval: -1]; // One second before the start of next month
return endOfMonth;
}
This is a 3 step process - add one month to the current date, find the start of the next month, then subtract 1 second to find the end of this month.
Swift 3
extension Date {
func startOfMonth() -> Date? {
let calendar = Calendar.current
let currentDateComponents = calendar.dateComponents([.year, .month], from: self)
let startOfMonth = calendar.date(from: currentDateComponents)
return startOfMonth
}
func dateByAddingMonths(_ monthsToAdd: Int) -> Date? {
let calendar = Calendar.current
var months = DateComponents()
months.month = monthsToAdd
return calendar.date(byAdding: months, to: self)
}
func endOfMonth() -> Date? {
guard let plusOneMonthDate = dateByAddingMonths(1) else { return nil }
let calendar = Calendar.current
let plusOneMonthDateComponents = calendar.dateComponents([.year, .month], from: plusOneMonthDate)
let endOfMonth = calendar.date(from: plusOneMonthDateComponents)?.addingTimeInterval(-1)
return endOfMonth
}
}
Swift 2
extension NSDate {
func startOfMonth() -> NSDate? {
let calendar = NSCalendar.currentCalendar()
let currentDateComponents = calendar.components(.CalendarUnitYear | .CalendarUnitMonth, fromDate: self)
let startOfMonth = calendar.dateFromComponents(currentDateComponents)
return startOfMonth
}
func dateByAddingMonths(monthsToAdd: Int) -> NSDate? {
let calendar = NSCalendar.currentCalendar()
let months = NSDateComponents()
months.month = monthsToAdd
return calendar.dateByAddingComponents(months, toDate: self, options: nil)
}
func endOfMonth() -> NSDate? {
let calendar = NSCalendar.currentCalendar()
if let plusOneMonthDate = dateByAddingMonths(1) {
let plusOneMonthDateComponents = calendar.components(.CalendarUnitYear | .CalendarUnitMonth, fromDate: plusOneMonthDate)
let endOfMonth = calendar.dateFromComponents(plusOneMonthDateComponents)?.dateByAddingTimeInterval(-1)
return endOfMonth
}
return nil
}
}

Try this trick.
Day Param: 1 is to Get first date of this month
Day Param: 0 is to Get last date of this month by getting last date of month previous to next month (means this month))
- (void)returnDate:(NSDate *)date {
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *comps = [calendar components:unitFlags fromDate:date];
NSDate * firstDateOfMonth = [self returnDateForMonth:comps.month year:comps.year day:1];
NSDate * lastDateOfMonth = [self returnDateForMonth:comps.month+1 year:comps.year day:0];
NSLog(#"date %#", date); // date 2013-06-20
NSLog(#"First %#", firstDateOfMonth); // firstDateOfMonth 2013-06-01
NSLog(#"Last %#", lastDateOfMonth); // lastDateOfMonth 2013-06-30
}
Next
- (NSDate *)returnDateForMonth:(NSInteger)month year:(NSInteger)year day:(NSInteger)day {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:day];
[components setMonth:month];
[components setYear:year];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
return [gregorian dateFromComponents:components];
}
Don't forget for right Date Formater
Updated for IOS 8.0
- (void)returnDate:(NSDate *)date {
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth;
NSDateComponents *comps = [calendar components:unitFlags fromDate:date];
NSDate * firstDateOfMonth = [self returnDateForMonth:comps.month year:comps.year day:1];
NSDate * lastDateOfMonth = [self returnDateForMonth:comps.month+1 year:comps.year day:0];
NSLog(#"date %#", date); // date 2013-06-20
NSLog(#"First %#", firstDateOfMonth); // firstDateOfMonth 2013-06-01
NSLog(#"Last %#", lastDateOfMonth); // lastDateOfMonth 2013-06-30
}
Next
- (NSDate *)returnDateForMonth:(NSInteger)month year:(NSInteger)year day:(NSInteger)day {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:day];
[components setMonth:month];
[components setYear:year];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
return [gregorian dateFromComponents:components];
}
Now your are working with:
NSCalendarUnitYear
NSCalendarUnitWeekOfMonth
NSCalendarIdentifierGregorian

Ok, since I'm rolling my own calendar control, I went ahead and created a NSCalendar category. Here's my lastOfMonth method:
- (NSDate *)lastOfMonth:(NSDate *)date
{
NSDateComponents *dc = [self components:NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit fromDate:date];
NSRange dim = [self rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:date];
dc.day = dim.length;
return [self dateFromComponents:dc];
}

For Swift 2.0 to get the first day of the current month:
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let dateComponents = calendar.components([NSCalendarUnit.Month, NSCalendarUnit.Year], fromDate: date)
let firstDay = self.returnDateForMonth(dateComponents.month, year: dateComponents.year, day: 1)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd-MMM-yy"
print("First day of this month: \(firstDay)") // 01-Sep-15
And the function to do this:
func returnDateForMonth(month:NSInteger, year:NSInteger, day:NSInteger)->NSDate{
let comp = NSDateComponents()
comp.month = month
comp.year = year
comp.day = day
let grego = NSCalendar.currentCalendar()
return grego.dateFromComponents(comp)!
}

You can get last date of month using :-
NSDate currDate=[NSDate date];
-(NSString *)getLastDateMonth:(NSDate *)currDate{
NSCalendar *gregCalendar=[[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *components=[gregCalendar components:NSMonthCalendarUnit|NSYearCalendarUnit fromDate:currDate];
NSInteger month=[components month];
NSInteger year=[components year];
if (month==12) {
[components setYear:year+1];
[components setMonth:1];
} else {
[components setMonth:month+1];
}
[components setDay:1];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateStyle:NSDateFormatterShortStyle];
NSString *lastDateOfMonth = [dateFormat stringFromDate:(NSDate *)[[gregCalendar dateFromComponents:components] dateByAddingTimeInterval:-86400]];
dateFormat=nil;
return lastDateOfMonth;
}

In Swift based in Nazir's answer
func getFirstAndLastDateOfMonth(date: NSDate) -> (fistDateOfMonth: NSDate, lastDateOfMonth: NSDate) {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let calendarUnits = NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth
let dateComponents = calendar?.components(calendarUnits, fromDate: date)
let fistDateOfMonth = self.returnedDateForMonth(dateComponents!.month, year: dateComponents!.year, day: 1)
let lastDateOfMonth = self.returnedDateForMonth(dateComponents!.month + 1, year: dateComponents!.year, day: 0)
println("fistDateOfMonth \(fistDateOfMonth)")
println("lastDateOfMonth \(lastDateOfMonth)")
return (fistDateOfMonth!,lastDateOfMonth!)
}
func returnedDateForMonth(month: NSInteger, year: NSInteger, day: NSInteger) -> NSDate? {
var components = NSDateComponents()
components.day = day
components.month = month
components.year = year
let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
return gregorian!.dateFromComponents(components)
}

Swift 5 getting last day of month - base on different sources
// -------------------------------------------------------
// lastDayOfMonth
// -------------------------------------------------------
static func lastDayOfMonth(year:Int, month:Int) -> Int {
let calendar:Calendar = Calendar.current
var dc:DateComponents = DateComponents()
dc.year = year
dc.month = month + 1
dc.day = 0
let lastDateOfMonth:Date = calendar.date(from:dc)!
let lastDay = calendar.component(Calendar.Component.day, from: lastDateOfMonth)
return lastDay
}

Looks like there is no need for any tricks or hacks, NSCalendar's rangeOfUnit does the job pretty nicely:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *dc = [[NSDateComponents alloc] init];
dc.year = 1947;
dc.month = 8; //desired month
//calculate start date
dc.day = 1; //As far as I can think start date of a month will always be 1
NSDate *start = [cal dateFromComponents:dc];
//calculate last date of month
NSRange dim = [cal rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:start]; // we used start date as it has the same month & year value as desired
dc.day=dim.length; //this is the simply the last day of the desired month
NSDate *last = [[NSCalendar currentCalendar] dateFromComponents:dc];
Log the values for verification:
NSLog(#"Start day of month Date: %#", start);
NSLog(#"Last day of month Date: %#", last);
Apple docs on NSCalendar rangeOfUnit: https://developer.apple.com/documentation/foundation/nscalendar/1418344-rangeofunit
p.s looks like this uses the same logic as #Scott Means's answer, but doesn't require any category, so use which ever answer you prefer!

Related

How to check if NSDate is in current week?

How to check if NSDate falls in current week of the year? I tried below but last week's date is also falling inside "Date is in this week" condition.
- (NSInteger)thisW:(NSDate *)date
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todaysComponents =
[gregorian components:NSWeekCalendarUnit fromDate:[NSDate date]];
NSUInteger todaysWeek = [todaysComponents weekday];
NSDateComponents *otherComponents =
[gregorian components:NSWeekCalendarUnit fromDate:date];
NSUInteger datesWeek = [otherComponents weekday];
NSLog(#"Date %#",date);
if(todaysWeek==datesWeek){
//NSLog(#"Date is in this week");
return 1;
}else if(todaysWeek+1==datesWeek){
//NSLog(#"Date is in next week");
return 2;
} else {
return 0;
}
}
What about this short extension in Swift 4?
extension Calendar {
func isDayInCurrentWeek(date: Date) -> Bool? {
let currentComponents = Calendar.current.dateComponents([.weekOfYear], from: Date())
let dateComponents = Calendar.current.dateComponents([.weekOfYear], from: date)
guard let currentWeekOfYear = currentComponents.weekOfYear, let dateWeekOfYear = dateComponents.weekOfYear else { return nil }
return currentWeekOfYear == dateWeekOfYear
}
}
A solution using the method rangeOfUnit:startDate:interval:forDate of NSCalendar to calculate the start date and the interval of the current week
- (BOOL)isInCurrentWeek:(NSDate *)date
{
NSDate *startDate = nil;
NSTimeInterval interval = 0.0;
NSCalendar *calendar = [NSCalendar currentCalendar];
// calendar.firstWeekday = 1; set the index of the first weekday if necessary
[calendar rangeOfUnit:NSWeekOfYearCalendarUnit startDate: &startDate interval: &interval forDate: [NSDate date]];
NSDate *endDate = [calendar dateByAddingUnit:NSSecondCalendarUnit value: (NSInteger)interval toDate: startDate options:NSCalendarMatchNextTime];
return [date compare:startDate] == NSOrderedDescending && [date compare:endDate] == NSOrderedAscending;
}
or in Swift
func isDateInCurrentWeek(_ date : Date) -> Bool
{
var startDate = Date()
var interval : TimeInterval = 0.0
let calendar = Calendar.current
// calendar.firstWeekday = 1 set the index of the first weekday if necessary
calendar.dateInterval(of: .weekOfYear, start: &startDate, interval: &interval, for: Date())
let endDate = calendar.date(byAdding:.second, value: Int(interval), to: startDate)!
return date >= startDate && date < endDate
}
I had to replace NSWeekCalendarUnit with NSCalendarUnitWeekOfYear
- (NSInteger)thisW:(NSDate *)date
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todaysComponents = [gregorian components:NSCalendarUnitWeekOfYear fromDate:[NSDate date]];
NSUInteger todaysWeek = [todaysComponents weekOfYear];
NSDateComponents *otherComponents = [gregorian components:NSCalendarUnitWeekOfYear fromDate:date];
NSUInteger datesWeek = [otherComponents weekOfYear];
//NSLog(#"Date %#",date);
if(todaysWeek==datesWeek){
//NSLog(#"Date is in this week");
return 1;
}else if(todaysWeek+1==datesWeek){
//NSLog(#"Date is in next week");
return 2;
} else {
return 0;
}
}
Swift 5.3.x, modified Vadian's answer. Other answers didn't work for me. For instance, test the method with the date from last year (2020), they return true.
Here's a Swift extension of NSDate because I have to use this function in an Objective-C class.
import Foundation
extension NSDate {
#objc func isInCurrentWeek() -> Bool {
var startDate = Date()
var interval : TimeInterval = 0.0
let calendar = Calendar.current
// calendar.firstWeekday = 1 set the index of the first weekday if necessary
calendar.dateInterval(of: .weekOfYear, start: &startDate, interval: &interval, for: Date())
let endDate = calendar.date(byAdding:.second, value: Int(interval), to: startDate)!
return (self as Date) >= startDate && (self as Date) < endDate
}
}
And sample test/use case:
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let d = "2021-01-23T13:56:49+0000"
let d2 = df.date(from: d)
print((d2! as NSDate).isInCurrentWeek()) // prints true, current date is Jan 21, 2021
Use this function to get number of week:
- (NSInteger)numberOfWeek:(NSDate *)date
{
NSCalendar *calender = [NSCalendar currentCalendar];
NSDateComponents *components = [calender components:NSCalendarUnitWeekOfYear fromDate:date];
return [components weekOfYear];
}
Using this code, you can compare week like this. I am just use next week date using dateWithTimeIntervalSinceNow: only for comparison.
if ([self numberOfWeek:[NSDate date]] == [self numberOfWeek:[NSDate dateWithTimeIntervalSinceNow: (60.0f*60.0f*24.0f*7.0f)]])
{
NSLog(#"Same Week");
}
else
{
NSLog(#"Different Week");
}
First get the firstday and lastday of the week of current date.
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *currentComps = [myCalendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekOfYearCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:[NSDate date]];
[currentComps setWeekday:1]; // 1: sunday
NSDate *firstDayOfTheWeek = [myCalendar dateFromComponents:currentComps];
[currentComps setWeekday:7]; // 7: saturday
NSDate *lastDayOfTheWeek = [myCalendar dateFromComponents:currentComps];
Now use a method given bellow putting your interested date
BOOL isInCurrentWeek = [self date:your given date isBetweenDate:firstDayOfTheWeek andDate:lastDayOfTheWeek];
NSLog(#"%d",isInCurrentWeek);
The expecting method
- (BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate
{
if ([date compare:beginDate] == NSOrderedAscending)
return NO;
if ([date compare:endDate] == NSOrderedDescending)
return NO;
return YES;
}

How to compose date from first NSDate and time from second NSDate into one NSDate?

I need one thing:
create one output NSDate that includes both of them with format: "yyyy-MM-dd HH:mm:00", where yyyy-MM-dd is from first NSDate and HH:mm:00 is from second NSDate
You can easily achieve this by creating a convenience initializer, like this:
convenience init(date: NSDate?, time: NSDate?) {
var combinedDate = NSDate()
if let date = date {
if let time = time {
let calendar = NSCalendar.currentCalendar()
let timeComponents = calendar.components(.HourCalendarUnit | .MinuteCalendarUnit | .TimeZoneCalendarUnit, fromDate: time)
var dateComponents = calendar.components(.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit, fromDate: date)
dateComponents.hour = timeComponents.hour
dateComponents.minute = timeComponents.minute
dateComponents.second = 0
dateComponents.timeZone = timeComponents.timeZone
if let dateFromComponents = calendar.dateFromComponents(dateComponents) {
combinedDate = dateFromComponents
}
}
}
self.init(timeInterval:0, sinceDate: combinedDate)
}
Basically it composes a date from components from two dates. For instance, it takes hours, minutes and seconds from the second NSDate called time, and year, month, and day from the first NSDate called date.
You can modify the components to make more or less accurate. You even extend the intializer to include customized units for the calendar.
Used this code
+ (NSDate *)combineDate:(NSDate *)date withTime:(NSDate *)time
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned unitFlagsDate = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *dateComponents = [gregorian components:unitFlagsDate fromDate:date];
unsigned unitFlagsTime = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *timeComponents = [gregorian components:unitFlagsTime fromDate:time];
[dateComponents setSecond:[timeComponents second]];
[dateComponents setHour:[timeComponents hour]];
[dateComponents setMinute:[timeComponents minute]];
NSDate *combDate = [gregorian dateFromComponents:dateComponents];
return combDate;
}
may help you
Swift 5 version:
init?(date: Date, time: Date) {
let calendar = Calendar.current
let timeComponents = calendar.dateComponents([.hour, .minute, .timeZone], from: time)
var dateComponents = calendar.dateComponents([.year, .month, .day], from: date)
dateComponents.hour = timeComponents.hour
dateComponents.minute = timeComponents.minute
dateComponents.second = 0
dateComponents.timeZone = timeComponents.timeZone
guard let combined = calendar.date(from: dateComponents) else { return nil }
self = combined
}
Assuming you have two strings:
NSDateFormatter *dateformate=[[NSDateFormatter alloc]init];
[dateformate setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *outputDate = [dateformate dateFromString:[#"2015-09-01" stringByAppendingString:#"08:33:00"]];

Number of weekend days in a month

How I can get number of weekends in month or between two NSDate ?
I was try do some tricks with
calendar.components( NSCalendarUnit.WeekCalendarUnit, fromDate: startDate, toDate: endDate, options: nil)
But no result
NSInteger count = 0;
NSInteger saturday = 7;
// Set the incremental interval for each interaction.
NSDateComponents *oneDay = [[NSDateComponents alloc] init];
[oneDay setDay:1];
// Using a Gregorian calendar.
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *currentDate = fromDate;
// Iterate from fromDate until toDate
while ([currentDate compare:toDate] == NSOrderedAscending) {
NSDateComponents *dateComponents = [calendar components:NSWeekdayCalendarUnit fromDate:currentDate];
if (dateComponents.weekday == saturday) {
count++;
}
// "Increment" currentDate by one day.
currentDate = [calendar dateByAddingComponents:oneDay
toDate:currentDate
options:0];
}
NSLog(#"count = %d", count);
According TENSRI I write code in swift with some fixs
func numberOfWeekdaysBeetweenDates(#startDate:NSDate,endDate:NSDate)->Int{
var count = 0
var oneDay = NSDateComponents()
oneDay.day = 1;
// Using a Gregorian calendar.
var calendar = NSCalendar.currentCalendar()
var currentDate = startDate;
// Iterate from fromDate until toDate
while (currentDate.compare(endDate) != .OrderedDescending) {
var dateComponents = calendar.components(.WeekdayCalendarUnit, fromDate: currentDate)
if (dateComponents.weekday == 1 || dateComponents.weekday == 7 ) {
count++;
}
// "Increment" currentDate by one day.
currentDate = calendar.dateByAddingComponents(oneDay, toDate: currentDate, options: nil)!
}
return count
}

Getting the first date of current quarter

I'm trying to get the first and the last date of current quarter, i'm using it:
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitQuarter | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
components.quarter = 1;
funStartDate = [[NSCalendar currentCalendar] dateFromComponents: components];
NSLog(#"First day of quater: %#", funStartDate);
[components setQuarter:[components quarter]+1];
funEndDate = [[NSCalendar currentCalendar] dateFromComponents: components];
NSLog(#"Last day of quater: %#", [funEndDate descriptionWithLocale:[NSLocale currentLocale]]);
But in both console print I see today's date. What I'm doing wrong?
UPDATED: I've found that Apple's bug with quarter unit is still there in iOS 7.1, so avoid using this unit in your date components.
Here I got working solution for you:
first day of a quarter:
NSDate *date = <whatever>;
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDate *startOfQuarter;
[currentCalendar rangeOfUnit: NSQuarterCalendarUnit
startDate: &startOfQuarter
interval: NULL
forDate: date];
NSLog(#"quarter starts at %#", startOfQuarter);
last day of a quarter:
NSDateComponents* comps = [currentCalendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay)
fromDate:date];
NSUInteger quartalNum = (comps.month - 1) / 3 + 1;
NSUInteger lastQuartalMonthNum = quartalNum * 3;
NSUInteger nextQuartalFirstMonth = lastQuartalMonthNum + 1
[comps setMonth: nextQuartalFirstMonth];
[comps setDay: 0]; // with 0 day we get last day of previous month
NSLog(#"quarter ends at %#", [currentCalendar dateFromComponents: comps]);
Swift 3.1. Quarter component still not working. Workaround:
extension Date {
public var startOfQuarter: Date {
let startOfMonth = Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
var components = Calendar.current.dateComponents([.month, .day, .year], from: startOfMonth)
let newMonth: Int
switch components.month! {
case 1,2,3: newMonth = 1
case 4,5,6: newMonth = 4
case 7,8,9: newMonth = 7
case 10,11,12: newMonth = 10
default: newMonth = 1
}
components.month = newMonth
return Calendar.current.date(from: components)!
}
}
Usage:
Date().startOfQuarter

Number of days between two NSDate objects

I'm trying to compare two days of NSDate objects, I used at the first time NSDateComponents to calculate difference between my two dates Objects, but it is working correctly.
NSString *dateStr =#"2012-11-05 15:00:00";
NSDate *date = [dateFormat dateFromString:dateStr];
NSDateComponents *datesDiff = [calendar components: NSDayCalendarUnit
fromDate: date
toDate: [NSDate date]
options: 0];
That does not resolve my problem. Indeed when date1 = 2012-11-05 23:00:00 and date2 = 2012-11-06 10:00:00, the difference between the tow dates is 0 day and 11 hours.
I am looking for something that allows me to detect day changes, in other words when date1 = 2012-11-05 23:00:00 and date2 = 2012-11-06 00:01:00, there's one day diffrence.
If someone knows the solution for that, i would welcome his suggestion.
Thanks in advance
I think you are looking for this (from the Date and Time Programming Guide):
Listing 13 Days between two dates, as the number of midnights between
#implementation NSCalendar (MySpecialCalculations)
-(NSInteger)daysWithinEraFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
{
NSInteger startDay=[self ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:startDate];
NSInteger endDay=[self ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:endDate];
return endDay-startDay;
}
#end
EDIT: Swift version:
extension NSCalendar {
func daysWithinEraFromDate(startDate: NSDate, endDate: NSDate) -> Int {
let startDay = self.ordinalityOfUnit(.Day, inUnit: NSCalendarUnit.Era, forDate: startDate)
let endDay = self.ordinalityOfUnit(.Day, inUnit: NSCalendarUnit.Era, forDate: endDate)
return endDay - startDay
}
}
NSString *start = #"2010-09-01";
NSString *end = #"2010-12-01";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [f dateFromString:start];
NSDate *endDate = [f dateFromString:end];
[f release];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components:NSDayCalendarUnit
fromDate:startDate
toDate:endDate
options:0];
[gregorianCalendar release];
components now holds the difference.
NSLog(#"%ld", [components day]);
func daysBetweenDates(startDate: NSDate, endDate: NSDate) -> Int
{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])
return components.day
}
or
let calendar = NSCalendar.currentCalendar();
let component1 = calendar.component(.Day, fromDate: fromDate)
let component2 = calendar.component(.Day, fromDate: toDate)
let difference = component1 - component2
For Swift 3:
Expanding from #masa's answer:
extension Calendar {
func daysWithinEraFromDate(startDate: Date, endDate: Date) -> Int? {
guard let startDay = ordinality(of: .day, in: .era, for: startDate) else {
return nil
}
guard let endDay = ordinality(of: .day, in: .era, for: endDate) else {
return nil
}
return endDay - startDay
}
}

Resources