Time zone in swift - NSDate - swift

i'm using xCode 7.2.1 ad Swift2, writing fo iOS.
i did a function for converting a String to a NSDate and that's :
class func StringToDateWithHour(data : String) -> NSDate
{
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(abbreviation: "CET");
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let date = dateFormatter.dateFromString(data) else{
return NSDate()
}
return date
}
I don't understand why i get back the UTC time, INSTEAD of CET time.
When i try to convert a string like : "2016-2-21 10:00:00" i get back
"2016-2-21 09:00:00" , one hour less.
Thank you.

You're saying that you want to convert 10 am CET to a NSDate.
That correctly outputs 9 am UTC time (UTC is one hour behind CET time).
NSDate objects don't depend on time zones, they're just data from a particular point in time.
NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).

Related

Swift configuring timezone with identifier changes GMT value

I have the following playground code:
let dateFormatter = ISO8601DateFormatter()
let zurichTimeZone = TimeZone(identifier: "Europe/Zurich")
dateFormatter.timeZone = zurichTimeZone
// dateFormatter.timeZone = .init(abbreviation: "GMT+1:00")
// prints timezone +1
print(dateFormatter.string(from: Date(timeIntervalSince1970: TimeInterval(100400))))
// prints timezone +2
print(dateFormatter.string(from: Date(timeIntervalSince1970: TimeInterval(1665957700))))
The first output is "1970-01-02T04:53:20+01:00" and the second output is "2022-10-17T00:01:40+02:00". Why does the GMT value change? If use "Europe/Kalingrad" as the identifier, I will get +3 from the first and +2 from the second print. The problem won't appear when I'm setting the timezone with "dateFormatter.timeZone = .init(abbreviation: "GMT+1:00")". I also can't find this behaviour when I'm using "Pacific/Guam".
The named TimeZones take daylight saving time (DST) into consideration, while the ones created by a GMT offset do not.
Zurich is GMT+1 in winter time, but GMT+2 in summer time.
The 2 dates you create are on different sides of the clock change, so 1 uses summer time, while the other uses winter time. This is where the 1h time difference using the 2 different timezones is coming from.

Issue Converting String to User Local Time using DateFormatter() Swift 4

I am trying to convert a string to a Date type. I am trying to convert to users local time, but I am getting a strange output. Here is the function that I am using and the results I am getting. The string input I am using looks like "10:15 AM:
The function below is returning a string, but that is just to look at the output, it will eventually return a Date.
func convertTime(date: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
dateFormatter.locale = Locale.current
print(Locale.current.identifier)
print(TimeZone.current.identifier)
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
if let formattedTime = dateFormatter.date(from: date) {
let userFormatter = DateFormatter()
userFormatter.timeStyle = .short // Set as desired
return userFormatter.string(from: formattedTime)
} else {
return "Unknown date"
}
}
the first part of the output is the input string, and the second part is the converted time. I expected to get the converted time in the America/Denver timezone, but tht is not the case.
en_US
America/Denver
Input String: 10:58 AM, Output String: 3:58 AM
en_US
America/Denver
Input String: 7:43 PM, Output String: 12:43 PM
en_US
America/Denver
Input String: 12:14 PM, Output String: 5:14 AM
Your output is correct for the code you posted. You treat the string "10:58 AM" as UTC time in the year 1. This is because the time string has no date and because you specific set the UTC timezone on the date formatter.
And you get the output of "3:58 AM" in local time (which is Denver for you). Denver is UTC-7 normally (UTC-6 during daylight saving time).
Your code is working correctly if your goal is to convert a UTC time to user's local time (Denver in this case).
If you want to treat the original string as local time and your goal is to just change the format, don't set the timeZone on the firs date formatter.
Unrelated but there's no need to use the line:
dateFormatter.locale = Locale.current
since the date formatter defaults to the current locale.

Swift get difference between two dates in GMT

I recently noticed strange behaviour trying to find the difference between two dates (in seconds).
I have a datestring that is in GMT time:
2016-01-07 01:09:47.289000
I want to find how many seconds since that time NOW.
But I notice that when I use NSDate() I get the time of my local time, not GMT time.
How would I go about doing this?
Use the NStimeZone class to set time zone
let date = NSDate()
var formatter = NSDateFormatter()
let gmt = NSTimeZone(abbreviation: "GMT")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
formatter.timeZone = gmt
formatter.stringFromDate(date)
To compare, convert the current date from NSDate to "GMT" and then calculate the time interval between the two.

NSDate set timezone in swift

how can i return a NSDate in a predefined time zone from a string
let responseString = "2015-8-17 GMT+05:30"
var dFormatter = NSDateFormatter()
dFormatter.dateFormat = "yyyy-M-dd ZZZZ"
var serverTime = dFormatter.dateFromString(responseString)
println("NSDate : \(serverTime!)")
the above code returns the time as
2015-08-16 18:30:00 +0000
The date format has to be assigned to the dateFormat property of the date formatter instead.
let date = NSDate.date()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let str = dateFormatter.stringFromDate(date)
println(str)
This prints the date using the default time zone on the device. Only if you want the output according to a different time zone then you would add for example
Swift 3.*
dateFormatter.timeZone = NSTimeZone(name: "UTC")
Swift 4.*
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
also refer link http://www.brianjcoleman.com/tutorial-nsdate-in-swift/
how can i return a NSDate in a predefined time zone?
You can't.
An instance of NSDate does not carry any information about timezone or calendar. It just simply identifies one point in universal time.
You can interpret this NSDate object in whatever calendar you want. Swift's string interpolation (the last line of your example code) uses an NSDateFormatter that uses UTC (that's the "+0000" in the output).
If you want the NSDate's value as a string in the current user's calendar you have to explicitly set up a date formatter for that.
Swift 4.0
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
If you always have the same time zone for the input string, you can create two date formatters to output the local time zone (or a specified one):
let timeFormatterGet = DateFormatter()
timeFormatterGet.dateFormat = "h:mm a"
timeFormatterGet.timeZone = TimeZone(abbreviation: "PST")
let timeFormatterPrint = DateFormatter()
timeFormatterPrint.dateFormat = "h:mm a"
// timeFormatterPrint.timeZone = TimeZone(abbreviation: "EST") // if you want to specify timezone for output, otherwise leave this line blank and it will default to devices timezone
if let date = timeFormatterGet.date(from: "3:30 PM") {
print(timeFormatterPrint.string(from: date)). // "6:30 PM" if device in EST
} else {
print("There was an error decoding the string")
}
The number 1 means 1 regardless of language. Yet in English it's spelled as one, in Spanish it's una, in Arabic it wahid, etc.
Similarly 123982373 seconds pass 1970 is going to reflect differently in different timezones or calendar formats, but's all still 123982373 seconds passed 1970
The difference between 3 seconds and 7 seconds is 4 seconds. That doesn't require a calendar. Neither you need a calendar/timezone to know the difference in time between these two Epoch times 1585420200 and 1584729000
Dates are just a timeInterval from January 1, 1970 (midnight UTC/GMT). Dates also happen to have a string representation.
Repeating Nikolia's answer, Swift's default string interpolation (2015-08-16 18:30:00 +0000) uses a DateFormatter that uses UTC (that's the "+0000" in the output).
Calendars with the use of timezones give us a contextual representation that is just easier to understand than trying to calculate the difference between two gigantic numbers.
Meaning a single date (think of a single timeInterval since 1970) will have a different string interpretations per calendar. On top of that a calendar will itself vary based on time zones
I highly recommend that you go and play around with this Epoch converter site and see how selecting a different timezone will cause the string representations for the same moment/date/timeInterval to change
I also recommend to see this answer. Mainly this part:
Timezone is just an amendment to the timestamp string, it's not considered by the date formatter.
To consider the time zone you have to set the timeZone of the formatter
dateFormatter.timeZone = TimeZone(secondsFromGMT: -14400)

How to Convert UNIX epoch time to Date and time in ios swift

I'm trying to convert the UNIX epoc time to datetime format using the below code
var epocTime = NSTimeInterval(1429162809359)
let myDate = NSDate(timeIntervalSince1970: epocTime)
println("Converted Time \(myDate)")
the actual result is (Thu, 16 Apr 2015 05:40:09 GMT) but am getting something like (47258-05-14 05:15:59 +0000) Can anyone please tel me how to achieve this.
update: Xcode 8.2.1 • Swift 3.0.2 or later
You need to convert it from milliseconds dividing it by 1000:
let epochTime = TimeInterval(1429162809359) / 1000
let date = Date(timeIntervalSince1970: epochTime) // "Apr 16, 2015, 2:40 AM"
print("Converted Time \(date)") // "Converted Time 2015-04-16 05:40:09 +0000\n"
Swift 5
I am dealing with a date in a JSON api which is defined as an Int and an example of the timestamp is 1587288545760 (UTC)
The only way I could display that value as a Date in a way that made any sense was to truncate the last 3 digits and convert THAT resultant date to "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
This was the function I created to achieve that.
func convertDate(dateValue: Int) -> String {
let truncatedTime = Int(dateValue / 1000)
let date = Date(timeIntervalSince1970: TimeInterval(truncatedTime))
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "UTC")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
return formatter.string(from: date)
}
It works for me and I end up with a date that looks like this:
"2020-04-19T09:29:05.000Z"
..and it reflects the fact that the original time stamp is exactly that date.
Hope that helps anyone having the same issue.
It seems that your time information is "milliseconds since 1970". Should have been straightforward to figure out: We are about 46 years after 1970, but your date is about 45,000 after 1970.
NSTimeInterval is based on SECONDS.
Convert your number to double and divide by 1000.0.