How to format a date using timezone in Swift? - ios

I have checked other questions but none of them helped me much.
I have following string:
let dateString = "2018-04-29T21:00:00.000Z"
I have successfully converted it to date using the following:
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let convertedDate = dateFormatter.date(from: dateString)
But now I only want the time "hh:mm a" using timezone such as "+8". I have tried following way but it's not working:
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC+8")
dateFormatter.dateFormat = "hh:mm a"
let requiredTime = dateFormatter.string(from: convertedDate!)
Can anyone help me to overcome this problem?

The format you want is hh:mm a Z, which will provide the +0800.
You want to create a TimeZone which +8 hours from GMT, normally I prefer to use the appropriate abrivations (ie AET), but I guess if you don't have that, you can create a TimeZone using secondsFromGMT, for example...
let tz = TimeZone(secondsFromGMT: 8 * 60 * 60)
let toFormatter = DateFormatter()
toFormatter.timeZone = tz
toFormatter.dateFormat = "hh:mm a Z"
let requiredTime = toFormatter.string(from: convertedDate!)
Which based on your example data, will produce a value of...
05:00 AM +0800

Related

Wrong date in swift 5 after conversion [duplicate]

This question already has answers here:
How can I parse / create a date time stamp formatted with fractional seconds UTC timezone (ISO 8601, RFC 3339) in Swift?
(13 answers)
Closed 3 years ago.
I am converting current date into GMT/UTC date string. But every time it returns me with wrong date.
My todays date is 07 February 2020, 11:09:20 AM. You can refer below image.
Here is my code :
let apiFormatter = DateFormatter()
//apiFormatter.dateStyle = DateFormatter.Style.long
//apiFormatter.timeStyle = DateFormatter.Style.long
//apiFormatter.calendar = Calendar.current
apiFormatter.timeZone = TimeZone.init(identifier: "GMT") //TimeZone(abbreviation: "UTC") //TimeZone.current //
//apiFormatter.locale = Locale.current
//apiFormatter.dateFormat = "yyyy-MM-DD HH:mm:ss"
apiFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
//apiFormatter.dateFormat = "yyyy-MM-dd'T'hh:mm:ssZ"
let endDate = apiFormatter.string(from: Date())
print(endDate)
And what I am getting in return is also you can check in image - 2020-02-38T05:33:34.598Z. I have tried with all the format, but no any luck. Can anyone suggest where it is going wrong?
First of all, the format should be:
apiFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
The Z is not a literal letter, it's the description of the time zone. However, making it a literal won't probably make a problem.
The 38 for day from your output is obviously caused by the DD format you have commented out.
Nevertheless, you have to set the locale:
apiFormatter.locale = Locale(identifier: "en_US_POSIX")
Otherwise you will have problems with 12/24h switching.
let apiFormatter = DateFormatter()
apiFormatter.locale = Locale(identifier: "en_US_POSIX")
// remove this if you want to keep your current timezone (shouldn't really matter, the time is the same)
apiFormatter.timeZone = TimeZone(secondsFromGMT: 0)
apiFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let endDate = apiFormatter.string(from: Date())
print(endDate) // 2020-02-07T08:25:23.470+0000
print(Date()) // 2020-02-07 08:25:23 +0000
Also note that you can use ISO8601DateFormatter instead of DateFormatter.
Try this and adjust according to what format you are getting from server -
private func getFormatedDateInString(_ dateString: String) -> String? {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
dateFormatter.timeZone = TimeZone(identifier: "UTC")
if let date = dateFormatter.date(from: dateString) {
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
dateFormatter.timeZone = TimeZone.current
let timeStamp = dateFormatter.string(from: date)
return timeStamp
}
return nil
}

DateFormater error only when running on iOS 13

I have a function to convert string to date format. This function works as expected on iOS 12 but on iOS 13. I get this error:
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
Here is my code:
func ConvertDateAndTimeFormat2() {
let timeDate = "2019-09-24 15:00:00 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
var dateObj:Date!
dateObj = dateFormatter.date(from: timeDate)
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
var timeObj:Date!
timeObj = timeFormatter.date(from: timeDate)
timeFormatter.dateFormat = "HH:mm"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
let timef = "\(timeFormatter.string(from: timeObj!))"
let Date = "\(dateFormatter.string(from: dateObj!))"
}
Please change your dateformat and use "yyyy-MM-dd HH:mm:ss Z" and try.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
For more details please visit https://nsdateformatter.com/
If you are trying to convert string time which in 24 hours format (Ex 15:25:00 / HH:mm:ss) then enable your device 24-Hour Time option. It might solve the issue in IOS 13.3
You may find the option here
Settings -> General -> Date & Time
There are many issues with your code. There is no reason to create two Date objects from one string. Just parse the original string once. Then you can create your date string and time string with the desired formats from that one date.
You should also use the special locale of en_US_POSIX when parsing fixed format date strings. There is also no need to set a timezone when parsing the original date string. The string provides its own timezone. The +0000 means it is UTC time.
You may not want to provide a timezone when converting the date to your final strings either. Most likely you want strings in the user's locale timezone, not some hardcoded timezone.
Here's your code cleaned up a lot:
func convertDateAndTimeFormat2() {
let timeDate = "2019-09-24 15:00:00 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
if let dateObj = dateFormatter.date(from: timeDate) {
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00") // Probably not needed
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "HH:mm"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00") // Probably not needed
let timef = timeFormatter.string(from: dateObj)
let datef = dateFormatter.string(from: dateObj)
print("Date: \(datef), time: \(timef)")
}
}
convertDateAndTimeFormat2()
Output:
Date: Tuesday, Sep 24, 2019, time: 18:00

what is the format I should use for the ISO timestamp in my case

I have a ISO 8061 format timestamp string "2018-06-13T12:11:13+05:00", what is the correct way to create Date object out from the String?
I tried:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let myDate = formatter.date(from: "2018-06-13T12:11:13+05:00")
But it doesn't work correctly, myDate is one hour behind. What is the format string I should use for this kind of timestamp?
For ISO 8601 time zone format
use ZZZZZ in capital
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
EDIT
Check the following example
I have just changed +05:30 from 05:00
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
formatter.timeZone = TimeZone(identifier: "UTC")
let myDate = formatter.date(from: "2018-06-13T12:11:13+05:30")
formatter.dateFormat = "yyyy-MM-dd HH:mm"
formatter.timeZone = TimeZone.current
print(formatter.string(from: myDate!))
Output
2018-06-13 12:11

Swift: Local Date object and local timezone

I've searched and searched, but most of the time posts talk about creating a localized string from a Date(). I need a date object to set a Timer to fire at the correct time.
I realize I might be missing something... This is the best I have so far:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy"
dateFormatter.locale = Locale.current
dateFormatter.timeZone = TimeZone.current
let todayDate = dateFormatter.date(from: "05/21/18")!
print(todayDate)
Which outputs:
2018-05-21 07:00:00 +0000
> Question: Why is there the +0000 if I set the dateFormatter variable timeZone to .current?
+ Update 01:
Following #MadProgrammer's comments:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy HH:mm:ss z"
dateFormatter.locale = Locale.current
dateFormatter.timeZone = TimeZone.current
let dateString = dateFormatter.string(from: Date())
let todayDate = dateFormatter.date(from: dateString)!
print(dateString)
print(todayDate)
Which Outputs, first one being correct:
05/21/18 19:29:19 PDT
2018-05-22 02:29:19 +0000
> Question: Why would creating a date from the dateFormatter.string(...) date object be so different?
Thank you in advance!

Converting a full date into just hours and minutes - Swift

I'm trying to do something very simple here and failing miserably. I just want to convert a string with a complete date into just the hours and minutes, can anyone see where I am going wrong? The following code prints nil
let dateString2 = "2018-03-11 20:43:05 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss +zzzz"
dateFormatter.locale = Locale.init(identifier: "en_GB")
let dateObj = dateFormatter.date(from: dateString2)
dateFormatter.dateFormat = "hh:mm"
print("Dateobj: \(dateFormatter.string(from: dateObj!))")
Your dateFormat String is flawed. hh is the 12hour time format, when you clearly receive a 24h time format, for which you need to use HH. Even though zzzz works, +0000 should actually be represented by z. When working with fixed time formats in most cases you should also set the locale to en_US_POSIX.
let dateString2 = "2018-03-11 20:43:05 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss z"
dateFormatter.locale = Locale.init(identifier: "en_US_POSIX")
let dateObj = dateFormatter.date(from: dateString2)
dateFormatter.dateFormat = "HH:mm"
print("Dateobj: \(dateFormatter.string(from: dateObj!))")
Output:
20:43
You need HH (24-hour) for the hour, not hh (12-hour). You also need to use the special locale of en_US_POSIX, not en_GB. You should also use Z for the timezone, not +zzzz.
let dateString2 = "2018-03-11 20:43:05 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
if let dateObj = dateFormatter.date(from: dateString2) {
dateFormatter.dateFormat = "HH:mm" // or "hh:mm a"
print("Dateobj: \(dateFormatter.string(from: dateObj))")
}

Resources