What is Difference among following time zones in swift - ios

let timeZone = NSTimeZone.system.description
let localTimeZone = TimeZone.ReferenceType.local.description
let currentTimeZone = TimeZone.current.description
let defaultTimeZone = TimeZone.ReferenceType.default.description
let autoUpdateTimezon = TimeZone.autoupdatingCurrent.description
print ("System Timezone \(timeZone)")
print ("Local Timezone \(localTimeZone)")
print ("Current Timezone \(currentTimeZone)")
print ("Default Timezone \(defaultTimeZone)")
print ("Auto updating Timezone \(autoUpdateTimezon)")
OUTPUT
System Timezone Asia/Kolkata (current)
Local Timezone Asia/Kolkata (autoupdatingCurrent)
Current Timezone Asia/Kolkata (current)
Default Timezone Asia/Kolkata (current)
Auto updating Timezone Asia/Kolkata (autoupdatingCurrent)
So, i get all the output are same so whats the difference among these timezone and which timezone we should use in which case.
Problem
I used following to code for the date conversion
static func stringToString(strDate:String, fromFormat:String, toFormat:String)->String{
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone.init(abbreviation: "UTC") ?? TimeZone(identifier: "UTC") ?? TimeZone.ReferenceType.default
dateFormatter.dateFormat = fromFormat
let currentDate = dateFormatter.date(from: strDate) ?? Date()
dateFormatter.dateFormat = toFormat
dateFormatter.timeZone = TimeZone.ReferenceType.default
let currentDates = dateFormatter.string(from: currentDate)
return currentDates
}
Scene : My app is crashing in qatar if user set timezone automatically and off the 24 hours, but in india there is no crash
(TimeZone.ReferenceType.local)
I have given next build with TimeZone.ReferenceType.default and issue is solved
So, i cant understand what was the issue.
Crash Report
Old Code in which i am getting crash

Note that TimeZone.ReferenceType is basically NSTimeZone.
If you look at the docs for TimeZone and NSTimeZone you'll find out very quickly.
From the NSTimeZone:
The system class property returns the time zone currently used by the system, if known. This value is cached once the property is accessed and doesn't reflect any system time zone changes until you call the resetSystemTimeZone() method. The local class property returns an autoupdating proxy object that always returns the current time zone used by the system.
To summarise, system is cached so won't change when the user changes their time zone. You have to call resetSystemTimeZone to update it. local on the other hand automatically updates when the user changes their time zone.
The same thing is true for TimeZone:
TimeZone provides two static functions to get time zone values: current and autoupdatingCurrent. The autoupdatingCurrent time zone automatically tracks updates made by the user.
current corresponds to system and autoupdatingCurrent corresponds to local.

Local -> An object that tracks the current system time zone. Use this property when you want an object that always reflects the current system time zone. from ios 11, the local class property reflects the current system time zone, whereas previously it reflected the default time zone.
System -> The time zone currently used by the system. If you access the system class property, its value is cached by the app and doesn't update if the user subsequently changes the system time zone. In order for the system property to reflect the new time zone, you must first call the resetSystemTimeZone() method to clear the cached value.
Default -> The default time zone for the current app.If no default time zone has been set, the current system time zone is used. If the current system time zone cannot be determined, the GMT time zone is used instead.The default time zone is used by the app for date and time operations. You can set it to cause the app to run as if it were in a different time zone.
Current -> The time zone currently used by the system.
autoupdatingCurrent -> The time zone currently used by the system, automatically updating to the user’s current preference.
Source -> https://developer.apple.com/documentation/foundation/nstimezone

Related

in swift, wrong time is displayed for a date outside daylight saving, depending on the time of call

i am currently having the following problem with relation to daylight saving.
Using the UI the user creates an entry for a specific date and time.
eg.: on 20.10 (so DST, this is the time where she is using the app) she creates an entry for 28.10 11:00 (this is outside the DST)
we create a date object like this, the format is the one used in the UI:
let dateFormatter = DateFormatter.getFormatter()
dateFormatter.dateFormat = "MMMM d, yyyy HH:mm"
self.startDate = dateFormatter.date(from: label.text!)!
no further processing is done and the date object is saved locally in realm.
printing the object shows 2020-10-28 09:00:00 +0000 which is correct, since we are in CET (GMT +2 in summer).
As long as the device's date is before 25.10 (so in DST) the date is correctly displayed throughout the app.
Now, after the DST (starting with 25.10) the app wrongly displays 28.10 10:00.
We are now in winter time which is GMT +1
it seems that swift wrongly uses the DST setting for the time when it is called, rather then the actual datetime that is being converted.
what am i doing wrong? any other technology that we used would correctly display the time, as long as the timezone is the same.

How to set timezone on a UIDatePicker?

Is there any way to set a UIDatePicker's timezone to mine (e.g. GMT+3)?
I have tried a lot of solutions on the internet, yet none work.
This is from the Apple docs:
Configuring a Date Picker The configuration of a date picker is
determined by the datePickerMode property, whose value you can set
programmatically or in Interface Builder. For modes that include date
or time values, you can also configure the locale, calendar, and time
zone information as appropriate. The date picker uses that information
when formatting date and time values for the current user, and
defaults to the device’s locale, calendar and time zone. The date
property represents the currently selected date in the form of an
NSDate object, which is calendar and time zone agnostic.
You can set the time zone by configuring the date picker. TimeZone.current will initialise a TimeZone object with the devices current time zone. You can also configure the calendar or locale if needed (though they default to the current device setting).
var picker = UIDatePicker()
picker.calendar = Calendar.current
picker.locale = Locale.current
picker.timeZone = TimeZone.current
You can retrieve the current date with the picker.date property. This can also be set programmatically to animate the date picker to that value.
You can use the date from the datepicker separately as well. You need a date formatter to apply calendar and timezone information:
let date = picker.date
let formatter = DateFormatter()
// Optionally set calendar, timezone etc on formatter
print(formatter.string(from: date))
#IBAction func onValueChanged(_ sender: UIDatePicker) {
print(sender.date.description(with: .current))
}
Reference:
Swift | iOS | XCode - UIDatePicker timezone problem fix
https://www.youtube.com/watch?v=_B9TyvFugy8

TimeZone changed while converting string to Date

When I'm changing date(which is in string form) to Date form,Then timezone change IST to UTC.Because of that I'm not getting notification
My code is :
#IBAction func datePickerDidSelectNewDate(_ sender: UIDatePicker) {
let selectedDate = sender.date
let dateStr = Date().currentTimeZoneDate(date: selectedDate as NSDate)
let date = dateFormatter.date(from: dateStr)
let delegate = UIApplication.shared.delegate as? AppDelegate
delegate?.scheduleNotification(at: date!)
}
In my code, I'm getting selectedDate is in UTC time zone.So I have converted it into currentTimeZone.But when I change String form to Date,means dateStrto date it again convert to UTC timeZone.
What is currentTimeZoneDate? This seems a deep misunderstanding of Date. Dates a never "in a time zone." Dates are an absolute point in time. All observers, no matter where they are, should agree on when a given Date occurs (ignoring relativistic effects).
You should configure UIDatePicker with the time zone you want it to represent. The default is localTimeZone, which always is the current time zone at the point that this action is called (so sender.date has already been adjusted). If you want it to represent some other time zone, change UIDatePicker.timeZone. Don't mess with the Date. Definitely don't convert it to a string and back.
It's unclear what scheduleNotification(at:) does, or what the final goal is. NSUserNotification by default will adjust all of its delivery dates if the time zone changes. If you don't want this (if you want to maintain the precise instant that the user selected, rather than the nominal time they selected), then you should set deliveryTimeZone on the notification (generally to NSTimeZone.default, which is a non-updating version of "the current time zone").
Swift's Date type (and also its Objective-C NSDate) doesn't have any notion of TimeZone in itself. It's just a simple timestamp. This means that if you set a timezone to a UIDatePicker, you can use its date as it is in that timezone without a need of converting it.
More explanation: when you po date in a debugger console, the debugger just select the UTC timezone as a presentation of the printing date. Its behavior doesn't related to the Date instance.

Ignoring time-zone changes after saving NSDate

My apps are time-zone agnostic: I want the dates and times saved and displayed in a manner that ignores changes in the user's time zone. Once I've recorded the local date/time of some user action in my app (typically by saving timeIntervalSince1970 in an sqlite DB), I want to show the same date/time string regardless if the user's time zone has changed or not, and regardless of the user's various time zone settings in his device.
For example, if a user's action occurs at 1:15 pm local time in San Francisco, and then he opens my app a few days later in New York, I want that prior action to still appear as 1:15 pm (not 4:15 pm), and even if he's manually set some other time zone in his device (e.g., Chicago). A second action in New York at 9:00 pm there, should forevermore display as 9:00 pm, even when back in California.
I could achieve my goal by saving every date/time as a string (based on the user's local time zone), and then never use the date methods again -- but then I couldn't do date/time arithmetic (e.g., sorting).
How can I be time-zone agnostic when saving and retrieving dates/times?
(Apple's Calendar app seems to behave this way when Time Zone Override is on, but only if I manually set the event time.)
Here's the working solution (#Hot Licks deserves the credit, but he didn't post an answer):
Subclass NSDate and add a gmtDate method that does the conversion from local TZ to GMT. gmtDate uses #"yyyy-MM-dd HH:mm" as the format string, which also drops seconds from the value. Like this:
+(NSDate *)gmtDate
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm"; // drops the seconds
dateFormatter.timeZone = [NSTimeZone systemTimeZone]; // the local TZ
NSString *localTimeStamp = [dateFormatter stringFromDate:[NSDate date]];
// localTimeStamp is the current clock time in the current TZ
// adjust date so it'll be the same clock time in GMT
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSDate *gmtDate = [dateFormatter dateFromString:localTimeStamp];
return gmtDate;
}
In didFinishLaunchingWithOptions: add [NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]] so all date formatters make date strings in GMT by default (but never include the timezone in the format string).
When the date/time of a user action needs to be saved, get the date via [NSDate gmtDate] and save that value in your database.
Record the time zone along with the timestamp. Use that time zone when formatting the timestamp later. You'll need to add another column to your database table.
Either save the time zone, as Rob suggested, or save the time as both an NSDate and a string. Use the string for the UI and the NSDate for calculations.
Or hey, do all three, if you need them.

Problem in getting DST time?

I am trying to get the time of other GMT value by using
Calendar c1 = Calendar.getInstance(TimeZone.getTimeZone(gmt));
but how can i get the DST time at that time zone.
The TimeZone class provides a getDSTSavings() method for a specific TimeZone Object. (JavaDoc: "Returns the amount of time to be added to local standard time to get local wall clock time.")
The Calendar interface provides two getOffset() methods, which let you find out the offset from UTC. (JavaDoc: "Returns the offset of this time zone from UTC at the specified date. If Daylight Saving Time is in effect at the specified date, the offset value is adjusted with the amount of daylight saving. ")
please see this piece of code to grok the complicated ways of java time:
#Test
public void testDST() {
final TimeZone met = TimeZone.getTimeZone("MET");
Calendar gc = new GregorianCalendar(met);
final long timeInMillis = gc.getTimeInMillis();
final long gmtTime= timeInMillis-(gc.getTimeZone().getOffset(timeInMillis));
final Date gmtDate = new Date(gmtTime);
System.out.printf("%-40s: %tc\n%-40s: %tc\n%-40s: %tc\n%-40s: %d\n%-40s: %d",
"new Date() (local timezone)",new Date(),
"UTC", gmtDate ,
"now from Calendar with TC GMT+02:00",gc,
"zoneoffset",gc.get(Calendar.ZONE_OFFSET),
"dst savings",met.getDSTSavings());
}
You can also define your own SimpleTimeZone and provide custom DST rules, however, i have not found out how to get this information from the predefined TimeZones.
You should also be aware, that if TimeZone.getTimeZone(TZName) does not find the specified timezone, it does not throw an exception, but it just uses GMT, which can cause major misunderstandings.
You can find all this information (and a lot more) in javadoc for Calendar, TimeZone, Date, etc.
There are few methods available in java.util.TimeZone to get Daylight Saving Time. Please check out the BlackBerry Java Docs page.

Resources