Swift - Nsdate and Last Week of Year

Swift - NSDate and last week of year

That dateAtWeekStart() method simply does not work.
[.YearForWeekOfYear, .WeekOfYear] are sufficient as calendar units to
determine the (start of a) week uniquely. The additional units can make
the calculation undetermined. Also you can not just set
components.weekday = 1 because in some regions Monday (2) is the first
day of the week.

So it is actually a bit easier:

extension NSDate {
func dateAtWeekStart() -> NSDate {
let cal = NSCalendar.currentCalendar()
// cal.firstWeekday = 1 // If you insist on Sunday being the first day of the week.
let flags : NSCalendarUnit = [.YearForWeekOfYear, .WeekOfYear]
let components = cal.components(flags, fromDate: self)
return cal.dateFromComponents(components)!
}
}

This should work in all cases and give the start of the week (at midnight) for the given date. There are also other methods
one could use, such as rangeOfUnit().

If you want Sunday to be considered as the first day of the week
instead of using the user's regional settings
then you have to set the firstWeekday property of the calendar.

The code to add days or weeks to a date also looks highly suspicious.
The extensions method for Int in the SwiftDate project treats
a day as 24*60*60 seconds. This is not correct, because in regions with
daylight saving times, a day can have 23 or 25 hours when the clocks
are adjusted. The correct way to add one week to a date is to
use calendar components again:

date = cal.dateByAddingUnit(.WeekOfYear, value: 1, toDate: date, options: [])!

Update for Swift 3:

extension Date {
func dateAtWeekStart() -> Date {
var cal = Calendar.current
// cal.firstWeekday = 1 // If you insist on Sunday being the first day of the week.
let components = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
return cal.date(from: components)!
}
}

Is a date in same week, month, year of another date in swift

You can use calendar method isDate(equalTo:granularity:) to check it as follow:

Xcode 11 • Swift 5.1

extension Date {

func isEqual(to date: Date, toGranularity component: Calendar.Component, in calendar: Calendar = .current) -> Bool {
calendar.isDate(self, equalTo: date, toGranularity: component)
}

func isInSameYear(as date: Date) -> Bool { isEqual(to: date, toGranularity: .year) }
func isInSameMonth(as date: Date) -> Bool { isEqual(to: date, toGranularity: .month) }
func isInSameWeek(as date: Date) -> Bool { isEqual(to: date, toGranularity: .weekOfYear) }

func isInSameDay(as date: Date) -> Bool { Calendar.current.isDate(self, inSameDayAs: date) }

var isInThisYear: Bool { isInSameYear(as: Date()) }
var isInThisMonth: Bool { isInSameMonth(as: Date()) }
var isInThisWeek: Bool { isInSameWeek(as: Date()) }

var isInYesterday: Bool { Calendar.current.isDateInYesterday(self) }
var isInToday: Bool { Calendar.current.isDateInToday(self) }
var isInTomorrow: Bool { Calendar.current.isDateInTomorrow(self) }

var isInTheFuture: Bool { self > Date() }
var isInThePast: Bool { self < Date() }
}

How do I find the beginning of the week from an NSDate?

you can use Calendar method date(from: DateComponents) passing [.yearForWeekOfYear, .weekOfYear] components from any date it will return the first day of the week from the calendar used. So if you would like to get Sunday just use Gregorian calendar. If you would like to get the Monday as the first day of the week you can use Calendar .iso8601 as you can see in this answer

Xcode 12 • Swift 5.3 or later (works with previous Swift versions as well)

extension Calendar {
static let gregorian = Calendar(identifier: .gregorian)
}


extension Date {
func startOfWeek(using calendar: Calendar = .gregorian) -> Date {
calendar.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
}
}

usage:

Date().startOfWeek()  // "Sep 20, 2020 at 12:00 AM"



If you would like to get the beginning of week at a particular timezone you just need to use a custom calendar:

var gregorianUTC = Calendar.gregorian
gregorianUTC.timeZone = TimeZone(identifier: "UTC")!
print(Date().startOfWeek(using: gregorianUTC)) // "2020-09-20 00:00:00 +0000\n"

How to check if NSDate is in current week?

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;
}

}

NSCalendar gives wrong week numbers by month in year

The result depends on calendar type, locale and first weekday of week settings.

The calendar on the mentioned website is based on ISO 8601, your currentCalendar() probably on Gregorian, both types are similar but not identical.

Please check this out in a playground and try also to uncomment the commented line and provide other locale identifiers.

The code is for Swift 2.0, in Swift 1.2 use .CalendarUnitWeekOfYear and .CalendarUnitMonth

let components = NSDateComponents()
components.year = 2016
components.month = 1

var weekNumbersForCalendarIdentifier = { ( identifier : String) -> [Int] in
let calendar = NSCalendar(calendarIdentifier: identifier)!
// calendar.locale = NSLocale(localeIdentifier: "us_POSIX")
let weekRange = calendar.rangeOfUnit(.WeekOfYear, inUnit: .Month, forDate: calendar.dateFromComponents(components)!)
return Array(weekRange.location..<weekRange.location + weekRange.length)
}

let resultISO = weekNumbersForCalendarIdentifier(NSCalendarIdentifierISO8601)
let resultGregorian = weekNumbersForCalendarIdentifier(NSCalendarIdentifierGregorian)

There is one particular behavior independent of the different settings:

NSCalendar displays the ordinal number 0 rather than the actual
number 52 or 53 of the preceding year.

NSDate from week number

There is an easier solution to your problem. You can use the nextDateAfterDate() method of NSCalendar:

let cal = NSCalendar.currentCalendar()
let comps = NSDateComponents()
comps.hour = 10
comps.weekday = cal.firstWeekday

let now = NSDate()
let fireDate = cal.nextDateAfterDate(now, matchingComponents: comps, options: [.MatchNextTimePreservingSmallerUnits])!

This gives the first date in the future which is at 10:00 on the first day of the week.

Get day of week using NSDate

What you are looking for (if I understand the question correctly) is NSCalendarUnit.CalendarUnitWeekday. The corresponding property of NSDateComponents is weekday.

Note also that your date format is wrong (the
full specification can be found here: http://unicode.org/reports/tr35/tr35-6.html).

The function can be simplified slightly, using automatic type inference, also you use variables a lot where constants are sufficient.
In addition, the function should return an optional which is nil
for an invalid input string.

Updated code for Swift 3 and later:

func getDayOfWeek(_ today:String) -> Int? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
guard let todayDate = formatter.date(from: today) else { return nil }
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: todayDate)
return weekDay
}

Example:

if let weekday = getDayOfWeek("2014-08-27") {
print(weekday)
} else {
print("bad input")
}

Original answer for Swift 2:

func getDayOfWeek(today:String)->Int? {

let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let todayDate = formatter.dateFromString(today) {
let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
let weekDay = myComponents.weekday
return weekDay
} else {
return nil
}
}

first and last day of the current month in swift

You get the first day of the month simply with

let components = calendar.components([.Year, .Month], fromDate: date)
let startOfMonth = calendar.dateFromComponents(components)!
print(dateFormatter.stringFromDate(startOfMonth)) // 2015-11-01

To get the last day of the month, add one month and subtract one day:

let comps2 = NSDateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = calendar.dateByAddingComponents(comps2, toDate: startOfMonth, options: [])!
print(dateFormatter.stringFromDate(endOfMonth)) // 2015-11-30

Alternatively, use the rangeOfUnit method which gives you
the start and the length of the month:

var startOfMonth : NSDate?
var lengthOfMonth : NSTimeInterval = 0
calendar.rangeOfUnit(.Month, startDate: &startOfMonth, interval: &lengthOfMonth, forDate: date)

For a date on the last day of month, add the length of the month minus one second:

let endOfMonth = startOfMonth!.dateByAddingTimeInterval(lengthOfMonth - 1)

Updated for Swift5:

extension Date {
var startOfDay: Date {
return Calendar.current.startOfDay(for: self)
}

var startOfMonth: Date {

let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.year, .month], from: self)

return calendar.date(from: components)!
}

var endOfDay: Date {
var components = DateComponents()
components.day = 1
components.second = -1
return Calendar.current.date(byAdding: components, to: startOfDay)!
}

var endOfMonth: Date {
var components = DateComponents()
components.month = 1
components.second = -1
return Calendar(identifier: .gregorian).date(byAdding: components, to: startOfMonth)!
}

func isMonday() -> Bool {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.weekday], from: self)
return components.weekday == 2
}
}


Related Topics



Leave a reply



Submit