static let calendar with autoupdatingCurrent time zone is not working - ios

In my application I have a static gregorian property in SharedCalendar class that is defined like this:
static let gregorian: Calendar = {
var calendar = Foundation.Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone.autoupdatingCurrent
return calendar
}()
When I want to access a day of some date in specific time zone I am calling:
SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day!
Let's say someDate is Date(timeIntervalSinceReferenceDate: 512658000.0) which is 2017-03-31 13:00:00 +0000.
When I start the app in Vancouver time zone the SharedCalendar.gregorian.timeZone property has value America/Vancouver (autoupdatingCurrent) and the result of SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day! is 31 which is correct.
When I put the application to background and switch the time zone to Sydney and run the app again the SharedCalendar.gregorian.timeZone property has value Australia/Sydney (autoupdatingCurrent) (which is correct), but the result of SharedCalendar.gregorian.dateComponents([ .day ], from: someDate).day! is 31 which is wrong (should be 1).
When I change the definition of gregorian property to be a var:
var gregorian: Calendar {
var calendar = Foundation.Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone.autoupdatingCurrent
return calendar
}
Everything works properly, which is for America/Vancouver (autoupdatingCurrent) I get 31, and for Australia/Sydney (autoupdatingCurrent) I get 1.
Right now I don't quite understand how TimeZone.autoupdatingCurrent is working. When device's time zone changes the SharedCalendar.gregorian.timeZone reflects the device's time zone, but it looks like SharedCalendar.gregorian is somehow using the old time zone.
Does anyone have explanation of this behaviour?

I reported radar regarding this issue and today Apple responded:
The reason that your static let calendar’s time zone doesn’t update is that you need to issue a call to NSTimeZone.resetSystemTimeZone() to sync up with the system time zone. See the documentation for NSTimeZone.resetSystemTimeZone() for more info: https://developer.apple.com/documentation/foundation/nstimezone/1387189-resetsystemtimezone?language=objc
The reason your var calendar works is because every call to the calendar property actually creates a new computed calendar, which happens to be set to a new time zone representing the current system time zone.
This makes sense, because static let caches system's time zone, and from documentation for NSTimeZone.resetSystemTimeZone we can read:
If the application has cached the system time zone, this method clears that cached object. If you subsequently invoke systemTimeZone, NSTimeZone will attempt to redetermine the system time zone and a new object will be created and cached (see systemTimeZone).

Related

How to get currentUTC time in swift

I want to set count down timer in swift. I have an option is to get current time is Date() but this method is giving wrong date time when my device time set wrong.
Is it possible to get exact current UTC time in swift, so I will set count down timer with exact time remaining.
Thanks.
The Date class doesn't have a timezone, it's just a "point int the time line" that's the same for all the timezones. When you use a DateFormatter to convert a date to a string (or a string to a date) you can specify the timezone like this:
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
If you cannot trust the device date you will have to use a NTP service like this:
https://github.com/instacart/TrueTime.swift
https://github.com/jbenet/ios-ntp
Get Date and Time from Apple Server
Many times, I have faced the same issue if the user changed his current time then lot's of logic will disturb, Unfortunately, no luck because of Date() always returns your device date.
In well-known game Candy crush, We can not play it for a specific time if my points got over, But if I change device time to feature time then everything will be unlocked. This is the best example of your problem.
You can use below-given web service or your web service to achieve your requirements. Below are some
free API's which provides date and time.
Geonames
Timezonedb
TrueTime
In addition to other answers, you can write an extension for Date class to get formatted Data in specific TimeZone to make it as utility function for future use. Like
extension Date {
func dateInTimeZone(timeZoneIdentifier: String, dateFormat: String) -> String {
let dtf = DateFormatter()
dtf.timeZone = TimeZone(identifier: timeZoneIdentifier)
dtf.dateFormat = dateFormat
return dtf.string(from: self)
}
}
Now you can call it like
Date().dateInTimeZone(timeZoneIdentifier: "UTC", dateFormat: "yyyy-MM-dd HH:mm:ss");

How to set lunar calendar UIDatePicker in iOS

I need switch UIDatePicker between Solar calendar and Lunar calendar. With Lunar calendar, I can get 02/30/2016 (MM/dd/yyyy), but with Solar calendar, its never get 02/30/2016 (MM/dd/yyyy). So, how can set it in UIDatePicker ?
I don't think it is possible, all supported calendars can be found in Apple Documentation
Lunar Calendar is also known is Chinese Calendar. Try these
self.datePicker.locale = Locale.init(identifier: "zh")
self.datePicker.calendar = Calendar.init(identifier: .chinese)
However, I tried both in simulator and with some app, there is no 2016/02/30 in Lunar. There is 2016/2/29 which convert to 2016/4/6 in Solar. There is 2015/02/30 Lunar (see below)
However, in the date picker, it shows all the leap months even it is invalid.

Firebase 2.0 - Store Date and Timezone

I need to store the date that something was created in the firebase database for a friend request, how can i store a date in firebase that i can work out how long ago since this date something happened. I would just store an NSDate in there but then what about timezones?
I dunno if firebase has something like Parse had where it would store date created and timezone automatically so you could read it from the server?
You need to set it up by yourself !
I use this code to do the timestamp. Hope this is what u want.
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy/MM/dd, H:mm:ss"
let defaultTimeZoneStr = formatter.stringFromDate(NSDate())
let post = ["\(key)":["username": username, "userPhoto": userPhotoUrl, "postPhoto": downLoadURL,"postText": postText!,"User":FIRAuth.auth()!.currentUser!.uid, "time":defaultTimeZoneStr] ]
self.DatabaseRef.child("posts").updateChildValues(post)

NSDate as function parameter in Swift

I'm facing an issue if I pass NSDate as a function parameter.
My code is:
self.PassDate(responseDate) ; // Response date value = 2015-05-15T00:00:00
func PassDate(date:NSDate) {
// Here ideally date value should be same as responseDate value.. but date is coming as 2015-05-14T07:00:00 PDT
}
Why passing NSDate is changing the timezone/values?
Nothing is changing. Different ways of viewing dates present them using different time zones. The underlying date is not changed. If you view the date in the debugger it (usually) shows it in UTC.
Try logging the date outside your function and inside using println() calls. You should see the same value in both places if you view it the same way each time.

Time picker shows wrong time iphone sdk

I have time picker in my app. I'm showing timePicker.date and the time is wrong.
NSLog is
NSLog (#"date : %#",[timePicker.date description]);
log is like date: 2012-02-07 17:00:01 +0000
i think that problem is in timezone
in ViewDidLoad i have this code
timePicker.locale = [NSLocale currentLocale];
timePicker.timeZone = [NSTimeZone localTimeZone];
but it isn't working...
Can somebody help me to solve my problem. Thanks
It is likely that the time picker is correctly applying time zone, but you're logging it using GMT rather than local time so that it just looks wrong. If you want to display the time returned from your time picker using local time, use NSDate's descriptionWithCalendarFormat:timeZone:locale: method, or use the NSDateFormatter class to get complete control over how your date is displayed.

Resources