DateComponents giving wrong date - ios

I am trying to convert today's date using DateComponents:
let calendar = Calendar.current
//add today's date
var todayDate = Date()
var dateComponents = calendar.dateComponents([.day, .month, .year], from: todayDate)
dateComponents.timeZone = TimeZone.current
todayDate = calendar.date(from: dateComponents)!
While debugging I found that after declaring todayDate, its value was 2016-11-11 07:44:44 +0000. After using dateComponents, the value changed to 2016-11-10 18:30:00 +0000. Whereas according to my location, the day should be 11th November, and the time should be somewhere between 1 or 2 PM. Why is this happening?

You haven't specified a timezone, nor hours minutes and seconds in your components. So, all these values are assumed to be zero. The resulting time is at midnight GMT on the year, month and day that you specified.
When you printed the result, you specified your current timezone, which appears to be 5h 30m different.
I'm guessing you are in India.

Related

Time output not as expected when using iOS SDK DateFormatter on Date set to Jan 1, 1

I have a scenario where dates are being on a server without the day aspect and just the time is needed. Therefore the day element is being stripped away before uploading to the server. Development up to this point (Point 1 in code below) cannot be changed as it is coming from an external source that is already in production.
We are then facing an issue when outputting this time back to the user. The time varies by minutes in different locations, even in the same timezone. Please check the code with comments below.
//1.
//Taking a date with just hours and minutes as I don't need the date.
//The timezone set (Europe/Rome) is different from the machine (Europe/Malta)
//Issue below still occurs if we use the same timezone as the machine.
let date = Date(timeIntervalSinceReferenceDate: 1570168800) //Result: Oct 4, 2050 at 8:00 AM
var calendar = Calendar.current
calendar.timeZone = TimeZone(identifier: "Europe/Rome")!
let comps = calendar.dateComponents([.hour, .minute], from: date)
let strippedDate = calendar.date(from: comps)! //Result: Jan 1, 1 at 8:08 AM
//the date outputted is bypassing the timezone setting and using the machine timezone when stripping out the day
//and keeping hours and minutes alone
//2.
//Outputing the date back to the user in different timezone identifiers
//These timezone identiers are all in the same timezone
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short;
dateFormatter.timeZone = TimeZone(identifier: "Europe/Paris")!
var formattedStart = dateFormatter.string(from: strippedDate) //Result: "7:19 AM"
dateFormatter.timeZone = TimeZone(identifier: "Europe/Rome")!
formattedStart = dateFormatter.string(from: strippedDate) //Result: "8:00 AM"
//This above appears correctly as it's coming from the same timezone that set up the starting date
dateFormatter.timeZone = TimeZone(identifier: "Europe/Malta")!
formattedStart = dateFormatter.string(from: strippedDate) //Result: "8:08 AM"
//The above appears the same as the stripped date which is the same as the machine used to create the stripped date
dateFormatter.timeZone = TimeZone(identifier: "Europe/Madrid")!
formattedStart = dateFormatter.string(from: strippedDate) //Result: "6:55 AM"
Referencing this answer, this issue is happening "Because at noon on November 18, 1883, the US and Canada railway companies began using a new, standard time system". Therefore since the date is being saved before this event, this might be the reason why we're getting varied minutes. However I still cannot find a solution to output the correct time.

iOS - How to get date always at midnight?

I am trying to get dates at midnight like, for example, 2019-08-01 00:00:00 +0000.
I have googled and tried to use all the possible answers that I found. But for some wired reason that I don't understand, none of them works.
I have used this code and I expect it to return 2019-08-08 00:00:00 +0000, it does 2019-08-08 22:00:00 +0000.
var calender = Calendar.current
calender.timeZone = Timezone.current
calender.startOfDay(for: Date()) // 2019-08-08 22:00:00 +0000
So what is the easiest way to find midnight date irrespective of the timezone? In other words, how to get midnight date according to the users timezone?
Your code is correct.
The last portion of the date string (+0000) represents the time zone. +0000 is Coordinated Universal Time (UTC), which includes the UK and western Africa. In other words, at midnight in the user's current time zone, it is 22:00 in London, England.
If you want to format your date to display the time stamp in the user's current time zone, you will have to use DateFormatter.
I live in Chicago, USA (-0500), and I've adjusted my timestamps accordingly
var calender = Calendar.current
calender.timeZone = TimeZone.current
let midnight = calender.startOfDay(for: Date()) // 2019-08-09 05:00:00 +0000
var dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone.current // Important!
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
dateFormatter.string(from: midnight) // 2019-08-09 00:00:00 -0500

How to find out what first day of week is? (Monday or Sunday)

I want to check if the first day of the week for a user is Monday or Sunday to perform some actions with the calendar. Is it possible to determinate that using NSCalendar or any other way?
It's just:
Swift:
Calendar.current.firstWeekday
Obj-C:
[NSCalendar currentCalendar].firstWeekday
With 1 = Sunday.
You can just use the firstWeekday property…
var calendar = Calendar.current
calendar.locale = Locale(identifier: "en_GB")
print("\(calendar.locale!) starts on day \(calendar.firstWeekday)")
// en_GB starts on day 2
calendar.locale = Locale(identifier: "en_US")
print("\(calendar.locale!) starts on day \(calendar.firstWeekday)")
// en_US starts on day 1
update
Per #maddy's comment below, Calendar.current will have the correct locale set for the current user.
let calendar = Calendar.current
print("\(calendar.locale!) starts on day \(calendar.firstWeekday)")
// en_GB starts on day 2 (in my case)

Swift 2.1 DatePicker setDate does not set date to current day and specified time

I am trying to set the minimum date to the current day on the date picker and then for the sake of user experience, set the time to 7pm or 19:00. For some reason it doesn't seem to be working. The minimum date setting works but the time doesn't get set. If I remove the minimum date line, the time gets set to 7pm, but strangely, the date gets set to Monday, Jan 1. Which isn't even this year.
Here's my code below:
datePicker.minimumDate = NSDate()
let calendar:NSCalendar = NSCalendar.currentCalendar()
let components = calendar.components([NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: NSDate())
components.hour = 19
components.minute = 00
datePicker.setDate(calendar.dateFromComponents(components)!, animated: true)
What am I doing wrong here?
Split that last line into:
let date = calendar.dateFromComponents(components)!
datePicker.setDate(date, animated: true)
Then look at the value of date. You'll find it is probably January 1, 2000 at the desired time.
Fix this by adding the year, month, and day components to:
let components = calendar.components([NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: NSDate())
In other words, you need:
let components = calendar.components([NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: NSDate())

How do I only allow day and date on Datepicker?

I have a date picker, and I want to limit the date picker to show the day and date and month, but the month can't be changed, it's attached to the date. i.e. Friday, January 15. January 15 is one component. It should show the current day plus the next 6 days, so one week. I don't want the year.
let gregorian: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let currentDate: NSDate = NSDate()
let components: NSDateComponents = NSDateComponents()
let minDate: NSDate = gregorian.dateByAddingComponents(components, toDate: currentDate, options: NSCalendarOptions(rawValue: 0))!
components.year = +7
let maxDate: NSDate = gregorian.dateByAddingComponents(components, toDate: currentDate, options: NSCalendarOptions(rawValue: 0))!
self.datepicker.minimumDate = minDate
self.datepicker.maximumDate = maxDate
First, you have to use two-section UIPickerView and and implement data source for with both month and day sections.
But actually it is not so easy as it seems. At least because you don't know how many days are in February since you don't choose a year.
Pardon my ignorance if I'm way off base here, but cannot NSDateFormatter be used here?
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMMM"
convertedDate = dateFormatter.stringFromDate(currentDate)

Resources