Getting incorrect start and end dates from weekOfYear - ios

When I run this code:
let calendar = Calendar.current
var dateComponents = DateComponents()
dateComponents.weekday = calendar.firstWeekday
dateComponents.weekOfYear = 2
dateComponents.year = 2017
let startOfWeek = calendar.date(from: dateComponents)
let endOfWeek = calendar.date(byAdding: .day, value: 6, to: startOfWeek!)
let formatter = DateFormatter()
formatter.dateStyle = .short
print(formatter.string(from: startOfWeek!))
print(formatter.string(from: endOfWeek!))
It prints this:
1/8/17
1/14/17
When I change the code to this:
dateComponents.weekOfYear = 1
dateComponents.year = 2017
It prints this:
12/31/17
1/6/18
Why is it 12/31/17?

When I use .full style to print the dates, I get Sunday, December 31, 2017 for the first date, but it's obviously wrong because December 31 is a Thursday.
If you want to get the correct date, use yearForWeekOfYear instead of year. Docs:
You can use the yearForWeekOfYear property with the weekOfYear and weekday properties to get the date corresponding to a particular weekday of a given week of a year. For example, the 6th day of the 53rd week of the year 2005 (ISO 2005-W53-6) corresponds to Sat 1 January 2005 on the Gregorian calendar.
Alternative, you can be a little naughty and not listen to the docs and use weekOfYear = 54:
let calendar = Calendar.current
var dateComponents = DateComponents()
dateComponents.weekday = calendar.firstWeekday
dateComponents.weekOfYear = 54
dateComponents.year = 2017
let startOfWeek = calendar.date(from: dateComponents)
let endOfWeek = calendar.date(byAdding: .day, value: 6, to: startOfWeek!)
let formatter = DateFormatter()
formatter.dateStyle = .short
print(formatter.string(from: startOfWeek!))
print(formatter.string(from: endOfWeek!))
This prints:
1/1/17
1/7/17
which is coincidentally, the correct dates.

Related

Why did date ordinality calculations change in iOS 12?

Try the following in playgrounds. Before iOS 12, it worked for all inputs (starting with 1):
input would equal output
let input = 1
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
var dateComponents = DateComponents()
dateComponents.day = input
dateComponents.hour = 0
dateComponents.minute = 0
dateComponents.second = 0
let date = Calendar.current.date(from: dateComponents)
let dateString = dateFormatter.string(from: date!)
let date2 = dateFormatter.date(from: dateString)
let output = Calendar.current.ordinality(of: .day, in: .era, for: date2!)
assert(output==input)
But, now in iOS 12, output and input will only be equal starting with an input of 577738... which is date: Oct 17, 1582, which is two days after the Gregorian calendar went into effect (source: https://en.wikipedia.org/wiki/Gregorian_calendar)
So, what's going on here? And why did this change in iOS 12?

How to get local time zone date in swift 3

I am getting year,month and day from a given date in this way.
let today=Date()
var calendar = Calendar.current
calendar.timeZone = .current
let components = calendar.dateComponents([.year, .month, .day], from: today)
let day=components.day
But I'm getting one day ahead from my current day. How can I solve this?
let date = Date().description(with: Locale.current)
print("date ---> \(date)")
Result: date ---> Tuesday, June 20, 2017 at 4:35:15 PM India Standard Time
I'm getting perfect system/local time.
You code is working,
let today=Date()
var calendar = Calendar.current
calendar.timeZone = .current
let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: today)
let day = components.day
let hour = components.hour
let minute = components.minute
print("day = \(day)\nhour = \(hour)\nminute = \(minute)")
Result: day = Optional(20) hour = Optional(16) minute = Optional(35)
Get Local Date and Time
Swift 5:
let today = Date()
let timeZone = Double(TimeZone.current.secondsFromGMT(for: today))
let localDate = Calendar.current.date(byAdding: .second, value: Int(timeZone), to: today) ?? Date()
As per the documentation:
If you want “date information in a given time zone” in order to
display it, you should use DateFormatter to format the date.
eg:
// If date is "Dec 7, 2018 at 6:34 AM" UTC
let today=Date() // is always UTC
var calendar = Calendar.current
calendar.timeZone = .current
let components = calendar.dateComponents([.year, .month, .day], from: today)
let day = components.day // Is 7
// To print with local version
let myFormatter = DateFormatter()
myFormatter.timeZone = TimeZone(secondsFromGMT: 3600*10)
myFormatter.dateFormat = "dd"
print(myFormatter.string(from: today)) // prints "07\n"
myFormatter.timeZone = TimeZone(secondsFromGMT: -3600*11)
print(myFormatter.string(from: today)) // prints "06\n"

How to get first date of month?

I am working on get start and end date from today’s date.
I am getting start and end date of current month by using
formula given by Martin R
Get first and last day of month
It is working perfectly.
My issue is how to put my custom value in this line
let components1 = calendar.components([.Year, .Month], fromDate: date)
Can I replace my custom month value to this code?
My requirement is:
I have one tableView for months like January, etc.
When I will click TableView I am getting current month according to tableview.
Suppose I click on January, I will get value 1.
So how to get start and end date of month using my custom month value?
My Code
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MM yyyy"
//To Get Start Date of Month
let components1 = calendar.components([.Year,.Day], fromDate: date)
components1.month = 3
let startOfMonth = calendar.dateFromComponents(components1)!
txtStartDate.text = dateFormatter.stringFromDate(startOfMonth)
try this code:
let calendar = NSCalendar.currentCalendar()
let date = "January 2016" // custom value
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMMM yyyy"
let components = calendar.components([.Year, .Month, .Day], fromDate: dateFormatter.dateFromString(date)!)
let startOfMonth = calendar.dateFromComponents(components)!
dateFormatter.dateFormat = "MM"
print(dateFormatter.stringFromDate(startOfMonth))
//NSLog("%# : %#", startOfMonth,dateFormatter.stringFromDate(startOfMonth));
Output:
01
I am answering my own question
temp number is month number like if January it will considered as 1.
plz go through this solution to get start and end date from custom values
thanks #Martin R
let calendar = NSCalendar.currentCalendar()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MM yyyy"
//To Get Start Date of Month
let components1 = calendar.components([.Year], fromDate: NSDate())
components1.month = Int(tempNumber!)!
let startOfMonth = calendar.dateFromComponents(components1)!
txtStartDate.text = dateFormatter.stringFromDate(startOfMonth)
//To Get End Date of Month
let comps2 = NSDateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = calendar.dateByAddingComponents(comps2, toDate: startOfMonth, options: [])!
txtEndDate.text = dateFormatter.stringFromDate(endOfMonth)

dateFromComponents gives Wrong date

I am trying to get a Date object from NSDateComponents, but Calendar.date(from: Components) is giving a date one day before the date that was in my original components.
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let dateComponents = calendar!.components([.Year , .Month , .Weekday, .Day], fromDate: NSDate())
dateComponents.year = 2015
dateComponents.month = 9
dateComponents.day = 1
po calendar!.dateFromComponents(dateComponents)
▿ Optional(2015-08-31 18:30:00 +0000)
- Some : 2015-08-31 18:30:00 +0000
Set the time zone with calendar object to UTC, and the try to get Date from the calendar.
calendar.timeZone = NSTimeZone(name: "UTC")!
It's giving you the UTC time zone, Just convert the Date by usning NSDateFormatter like this, you will get your answer -
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let dateComponents = calendar!.components([.Year , .Month , .Weekday, .Day], fromDate: NSDate())
dateComponents.year = 2015
dateComponents.month = 9
dateComponents.day = 1
let df = NSDateFormatter()
df.dateFormat = "yyyy-MM-dd"
let datestring = df.stringFromDate(calendar!.dateFromComponents(dateComponents)!)
print(datestring)

Swift - Get date from day of year

We can get day of year for date using below line.
let day = cal.ordinalityOfUnit(.Day, inUnit: .Year, forDate: date)
But how can we get the date from day of year?
If you know the year you can get DateComponents date property as follow:
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
let now = Date()
let day = Calendar.iso8601.ordinality(of: .day, in: .year, for: now)! // 121
let year = Calendar.iso8601.component(.year, from: now) // 2017
let date = DateComponents(calendar: .iso8601, year: year, day: day).date // "May 1, 2017, 12:00 AM"
or using DateFormatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy D"
if let date = dateFormatter.date(from: "\(year) \(day)") {
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .short
dateFormatter.string(from: date) // "May 1, 2017, 12:00 AM"
}
You cannot go the other way. Going from a date to a day of the year discards all other information, you are left with only the day of the year (you no longer know what year). To go back to a full date you would have to make assumptions about the year the day was in.
The answer that #LeoDabus gave is more succinct than this, so it is perhaps the better choice. Having said that, this is the code that I would have used:
let dateComponents = NSDateComponents();
dateComponents.year = 2015
dateComponents.day = day
let calendar = NSCalendar.currentCalendar()
let date = calendar.dateFromComponents(dateComponents)
Updated for Swift 4:
let dateComponents = NSDateComponents();
dateComponents.year = 2018
dateComponents.day = someDay
let calendar = NSCalendar.current
let date = calendar.date(from: dateComponents as DateComponents)

Resources