date is not printing properly for UIDatePicker - swift

I have a date picker & above it I have 1 button as Done. On clicking this button I print the date picker date.
When I scroll the date picker and print date, it works fine. Below is the code I have
print("date selected===\(myDatePicker.date)")
The problem comes when I don't scroll the datepicker and click done button.
The scenario is I have set datepicker maximumDate as year 2000 (currentYear-18). Below is code I have used.
var dayComp = DateComponents()
currDate = Date()
dayComp.year = -18
currDate = calendar.date(byAdding: dayComp, to: currDate)!
mDateFrom.maximumDate = currDate
Now as datepicker is going back 18 years, I see date picker with date as 25/Jul/2000 however when I click Done button it print today date only.
It gives proper date only when I scroll datepicker.
Any idea why this is happening?

I believe you need to set the default date displayed by the date picker once you create a datePicker based on what you want it to be. Because the default value of this property is the date when the UIDatePicker object is created and that's why whenever you print the value of date picker without spinning, it shows you the current date however if you spin the datePicker, this property is being set properly and you get the right date printed.
//you can use date property to set or get
myDatePicker.date = yourFormattedDateHere
Setting date property animates the date picker by spinning the wheels to the new date and time, if you don't want any animation to occur when you set the date, use the setDate(_:animated:) method, passing false for the animated parameter.

Related

Working with Date() in Swift and having issues adjusting timezones for storing and reading back in Firestore/Firebase

I am storing dates from a Swift Project in Firestore without any problem. Dates are converted into UTC format and stored in Firestore as a Timestamp. All good.
Then, back on clientside, I can read them back and apply the TimeZone.current and the date/time are adjusted accordingly based on the timezone the user is currently in.
So, as en example, a time originally of:
9:00 pm Melbourne time (which is GMT+10),
shows as 7:00 am if the user is in New York.
Great.
But I have some items that I want to adjust for timezones (as per above) and others I don't.
So say I have two items the same as the above example, but one is an alarm and I want to keep at the time it was originally set for regardless of the new timezone... So still keep it at 9:00 pm.
I have a Bool flag saved in my database to say ignoreTimezone but I'm lost as to how to do this in Swift when reading back the timestamp from Firestore in UTC format and get it back to the original 9:00 pm.
All the Q&A's I've found are all about converting timezones etc. but not really on this example of ignoring one and keeping the date and time set to the timezone they were originally set for.
Thanks in advance for any help and/or suggestions.
Question updated as recommended
I have now incorporated the suggested code. So have a calendar extension:
extension Calendar {
func offsetFromMidnight(for date: Date) -> TimeInterval {
return date.timeIntervalSince(startOfDay(for: date))
}
}
Then I carry out the recommended steps.
Take an offset from midnight, in this case, the current Date():
let offsetSinceMidnight = UInt64(Calendar.current.offsetFromMidnight(for: Date()))
This value is then stored on the server.
I'm currently in Melbourne (Australia), so the date and time item used for testing is July 9 # 2:00pm.
When it is retrieved on the client end in a different timezone, I'm using the recommended code:
//Create a calendar for the target timezone
guard let chicagoTimeZone = TimeZone(identifier: "America/Chicago") else { fatalError() }
var chicagoCalendar = Calendar(identifier: .gregorian)
chicagoCalendar.timeZone = chicagoTimeZone
//Calculate midngiht in the target calendar
let chicagoMidnight = chicagoCalendar.startOfDay(for: Date())
//calculate the same time-of-day in the new timezone
let adjustedChicagoTime = Date(timeInterval: TimeInterval(offsetSinceMidnight), since: chicagoMidnight)
The output is set to the correct time, 2:00pm in Chicago, but because of the differnent dates (Chicago is still July 8th), then the midnight timeinterval is being applied on the wrong date. So I get July 8 # 2:00pm.
I'm assuming I will also need to capture the original date components to apply the offsetSinceMidnight to a date in the newTimeZone that has matching date components??? Or is there a better approach to this?
Date objects store an instant in time, anywhere in the world. They don't capture the idea of a time-of-day regardless of time zone.
To do that I would suggest calculating an offsetFromMidnight value.
Edited to fix return value.
extension Calendar {
func offsetFromMidnight(for date: Date) -> TimeInterval {
return date.timeIntervalSince(startOfDay(for: date))
}
}
You'd call that function in the user's current calendar to get the seconds since midnight in the user's current time zone. Save that to your database. (You could round to a long integer with very little loss of precision.)
I happen to BE in the NYT time zone (EDT) so using that as the destination time zone won't work for me since it won't change anything. Instead, I'll show code to convert from my timezone to GMT:
//Run on user's local machine (in EDT in my case):
let offsetSinceMidnight = UInt64(Calendar.current.offsetFromMidnight(for: Date()))
//Save offset to FireStore
Then if you want that same time of day in a new timezone, you'd use code like this:
//Create a calendar for the target time zone (or the user's local time zone on the destination machine)
guard let gmt = TimeZone(abbreviation: "GMT") else { fatalError() }
var gmtCalendar = Calendar(identifier: .gregorian)
gmtCalendar.timeZone = gmt
//Read time offset from FireStore
let offsetFromNYC = Calendar.current.offsetFromMidnight(for: Date())
//Calculate midnight in target calendar
let gmtMidnight = gmtCalendar.startOfDay(for: Date())
//Calculate the same time-of-day in the GMT time zone
let gmtTimeToday = Date(timeInterval: TimeInterval(offsetSinceMidnight), since: gmtMidnight)
print(gmtTimeToday)
Note that the above will give you the same hours/minutes/seconds as the offsetFromMidnight time.
Edit:
If your goal is to set an alarm to the next future time-of-day in the local time zone, you'd need to add logic to check if the computed date/time is in the past and adjust:
//Change adjustedChicagoTime to a var
var adjustedChicagoTime = Date(timeInterval: TimeInterval(offsetSinceMidnight), since: chicagoMidnight)
//If the alarm time is in the past, add a day to the date.
if adjustedChicagoTime < Date() {
adjustedChicagoTime = Calendar.current.date(byAdding: .day,
value: 1, to: adjustedChicagoTime, wrappingComponents: false)
}
Edit #2:
After a back-and-forth, it sounds like you sometimes want to save a date and time that's independent of time zone, like 9:30 AM on 10 July. If I create that date in EDT, and you view it in Melborne, it's ALWAYS 9:30 AM on 10 July.
Other times, you want to upload and download dates & times that honor time zones.
In order to easily do both, I would suggest saving 2 different string date/time fields to FireStore, one with a time zone, and one without. The one with timezone (or rather offset from GMT) would capture a moment in time around the world, and could be converted to a local time.
The one without time zone would describe a day/month/year/hours/minutes in local time.
You could generate/parse those strings in Swift using date formatters like this:
let baseFormatString = "YYYY-MM-dd'T'HH:mm"
let timeZoneFormatString = baseFormatString + "ZZZ"
let noTimeZoneFormatter = DateFormatter()
noTimeZoneFormatter.dateFormat = baseFormatString
let timeZoneFormatter = DateFormatter()
timeZoneFormatter.dateFormat = timeZoneFormatString
Note that by default a date formatter uses the system's time zone, so the "no time zone formatter" would assume the local time zone. If you use it to convert a date string to a date, it will assume the date is in the local time zone.

MomentJS date string adds one day

I don't understand why this date is saved as +1 day:
startdate = "2017-11-29T23:59:59.999Z";
var new_date = moment(startdate).format('DD/MM/YYYY'); // --> gives 30/11/2017
But if I do:
startdate = "2017-11-29";
var new_date = moment(startdate).format('DD/MM/YYYY'); // --> gives the correct date 29/11/2017
Any ideas?
Here is a jsfiddle showing this: http://jsfiddle.net/jbgUt/416/
Thanks!
If a time part is included, an offset from UTC can also be included as +-HH:mm, +-HHmm, +-HH or Z.
Add utc() to avoid it.
moment(startdate).utc().format('DD-MM-YYYY')
or
moment.utc(startdate).format('DD-MM-YYYY')
If you want to parse or display a moment in UTC, you can use moment.utc() instead of moment()
Late to the party on this one, but I did just convert a few of our product's date-time objects to https://moment.github.io/luxon/
Takes out the need for the .utc() method above.

Swift: Set custom Date(Day only) in DatePicker

I have two date pickers. Let's say fromDatePicker and untilDatePicker. I set the untilDatePicker to current date (ex: 12/06/17) and I want to set the fromDatePicker into first date of the current month (ex: 01/06/17) but I don't have any idea to set the untilDatePicker.
I have read this question but it's not helped me much.
This is swift3 solution and how you set first day of current month in datePicker , if you need to get first of other month just change date variable with some day from that month
let date = NSDate()
let calendar = NSCalendar.current
let components = calendar.dateComponents([.year,.month], from: date as Date)
let startOfMonth = calendar.date(from: components)
self.datePicker.setDate(startOfMonth!, animated: true)

How can I set the first day of the week to monday in dojox.calendar (columnview)

How can I set the first day of the week to monday in dojox.calendar (columnview)?
http://dojotoolkit.org/reference-guide/1.9/dojox/calendar.html
In the documentation it says there is a startDate property in the columnView,
but you have to set a date. How can I set the startDate on Monday?
If I set a startDate, nothing changes.
startDate * - The date of the first column,
Properties with an (*) are computed by the calendar widget.
The calendar renders the startdate from the locale of the browser.

display a date from the other calendar as selected

I have two calendar, when I select fist calendar value then my second calendar will shows previous calendar value +2 as selected ( i.e. when I select 2/07/2012 from first calendar then my second calendar will shows 4/07/2012 )
Is it possible?
Simply create a new date by adding the appropriate amount of seconds:
NSDate *newDate = [selectedDate dateByAddingTimeInterval:60*60*24*2];
and use that date as the basis for your new calendar.