MST to IST wrong timezone conversion by abbreviation - ios

In my code I am getting time and its format time zone like "IST", "MST" from a server and by using that I need to convert a given time to local device's time. For that I am using TimeZone(abbreviation:) method and its working fine with all formats except "MST" format. I am getting converted time one hour after.
In following code I am getting output as 04:30PM and 04:29PM which is one hour after the actual time. (here given time's format is "MST")
let startDateString = "04:00:00" // expected 3:30pm after convertine to IST
let endDateString = "03:59:59"
let timeZoneString = "MST"
func getTime() {
if let scheduleTimeZone = TimeZone(abbreviation: timeZoneString) {
let startScheduledTime = toScheduledTime(startDateString, using: scheduleTimeZone)
let endScheduledTime = toScheduledTime(endDateString, using: scheduleTimeZone)
print(startScheduledTime)
print(endScheduledTime)
}
}
/// Method to get local time for scheduled time
func toScheduledTime(_ time: String, using timeZone: TimeZone) -> String {
let today = "2022-05-09"
guard let dateTimeScheduleTZ = (today + " " + time).dateTime(createWithTZ: timeZone,
format: "yyyy-MM-dd HH:mm:ss") else {
return ""
}
return dateTimeScheduleTZ.dateTime(createLocal: "hh:mma")
}
extension String {
func dateTime(createWithTZ timeZone: TimeZone,
format: String) -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
dateFormatter.timeZone = timeZone
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
guard let date = dateFormatter.date(from: self) else {
return nil
}
return date
}
}
extension Date {
func dateTime(createLocal format: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
dateFormatter.timeZone = TimeZone.current
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
return dateFormatter.string(from: self)
}
}
getTime()

Related

Date time conversion in swift 5

I want to convert 2021-04-23T07:43:52.532656+00:00 to 04 April, 2021 7:43 Am
I am getting the day month and year correct but I have problems when formatting the time can somebody help me
My problem when converting time - I want the same time but when formatting it goes to the current time zone
func dateFormating(date : String) -> Date{
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"//yyyy-MM-dd'T'HH:mm:ssZ
// var localTimeZoneAbbreviation: String { return TimeZone.current.abbreviation() ?? "UTC" }
// dateFormatter.locale = Locale.init(identifier: localTimeZoneAbbreviation)
// dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = NSTimeZone.local
return dateFormatter.date(from: date) ?? Date()
}
func dateConverter(date : Date) -> String {
print("date in here 1 = \(date)")
let dateFormatterNormal = DateFormatter()
dateFormatterNormal.dateFormat = date.dateFormatWithSuffix()
// var localTimeZoneAbbreviation: String { return TimeZone.current.abbreviation() ?? "UTC" }
// dateFormatterNormal.locale = Locale.init(identifier: localTimeZoneAbbreviation)
// dateFormatterNormal.locale = Locale(identifier: "en_US_POSIX")
// dateFormatterNormal.timeZone = TimeZone.current
let endDate = dateFormatterNormal.string(from: date )
print("endinf date == \(endDate)")
return endDate
}
func dateFormatWithSuffix() -> String {
return " MMM , yyyy h:mm a"
}

Using DateFormatter to parse this string into a Date?

I'm hitting a webservice that is returning a string in the following format:
"yyyy-MM-dd'T'HH:mmZ"
It's very close to the standard UTC format, but just without the ss at the end. My issue is that my dateFormatter is always returning nil...and I have tried to make sure that locale and everything else is setup properly.
Here is an example of an actual string:
2019-12-26T00:00Z
Here is the code that creates the DF:
extension DateFormatter {
#objc static func defaultDateFormat(_ format: String) -> DateFormatter {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "US")
formatter.dateFormat = format
return formatter
}
func date(from string: String?) -> Date? {
if let string = string {
return self.date(from: string)
} else {
return nil
}
}
func string(fromOptional date: Date?) -> String? {
if let date = date {
return self.string(from: date)
} else {
return nil
}
}
func string(fromOptional date: Date?, defaultStr: String) -> String {
return self.string(fromOptional: date) ?? defaultStr
}
}
let df = DateFormatter.defaultDateFormat("yyyy-MM-dd'T'HH:mmZ")
let date: Date? = df.date(from: __dateString__) // always nil
A few observations:
You want to use a locale of en_US_POSIX, an invariant locale that always works for ISO 8601 / RFC 3339 date strings. See Technical Q&A 1480.
If you want to use this formatter to convert a date back to a string like 2019-12-26T00:00Z, you will want to:
Use X (or ZZZZZ or XXXXX) in your format string, not Z (see the “zone” section in the table at Date Format Patterns and you’ll see how these various time zone patterns, e.g. Z, ZZZZZ, and X, are interpreted); and
Set the timeZone of the formatter to use Zulu/GMT/UTC.
Thus:
#objc static func defaultDateFormat(_ format: String) -> DateFormatter {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = format
return formatter
}
And
let df = DateFormatter.defaultDateFormat("yyyy-MM-dd'T'HH:mmX")
let date = df.date(from: "2019-12-26T00:00Z")
Or
let string = df.string(from: Date())

How to change string datetime format to another format using Swift

I am trying to change date time concatenation and changing string input format to another format. I tried below code. Here, I can able to change the date format but need to concatenate current time before passing input date string.
My Code Below
override func viewDidLoad() {
super.viewDidLoad()
let result = formattedDateFromString(dateString: "28 Aug, 2019", withFormat: "dd-MM-yyyy")
self.resultLabel.text = result
}
func formattedDateFromString(dateString: String, withFormat format: String) -> String? {
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "dd/MM/yyyy"
if let date = inputFormatter.date(from: dateString) {
let outputFormatter = DateFormatter()
outputFormatter.dateFormat = format
return outputFormatter.string(from: date)
}
return nil
}
Expected output like :
28-08-2019 5:00 PM
func formattedDateFromString(dateString: String, withFormat format: String) -> String? {
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "dd MMM, yyyy"
if let date = inputFormatter.date(from: dateString) {
print(date)
let outputFormatter = DateFormatter()
outputFormatter.dateFormat = format
return outputFormatter.string(from: date)
} else {
print("nope")
}
return nil
}
let result = formattedDateFromString(dateString: "28 Aug, 2019", withFormat: "dd-MM-yyyy - h:mm a")
print(result)
Outputs:
"28-08-2019 - 12:00 AM"
In general I found this website to be really useful when trying to reason about dates in Swift/Objective-C
You can use this function
func convDate(dateToConvert: String) -> String? {
//Input Format
let df = DateFormatter()
df.dateFormat = "dd LL, YYYY"
//Convert input date string to date
guard let date = df.date(from: dateToConvert) else { print("Incorrect date format"); return nil }
//Output format
let outDF = DateFormatter()
outDF.dateFormat = "dd-MM-YYYY"
let hourDF = DateFormatter()
hourDF.dateFormat = "h:mm a"
hourDF.amSymbol = "AM"
hourDF.pmSymbol = "PM"
//format to string dd-MM-YYYY H:mm a
return outDF.string(from: date) + " " + hourDF.string(from: Date())
}
example
print(convDate(dateToConvert: "13 Aug, 2019"))

Date picker shows a different date (1 day behined) from when picked

I have a UIDatePicker that is connected to a UILabel. I want the user to pick a birthday that is more than 18 years ago (age restriction). So I have this line to set the maximumDate value:
datePicker.maximumDate = NSCalendar.currentCalendar().dateByAddingUnit(.Year, value: -18, toDate: NSDate(), options: [])
This line however causes the picker to show a 1 day behind the selected date. for example if I choose September 27, 1956 on the picker the label shows September 26, 1956 I believe it has to do with NSDate() using a different timezone one that is behind my local timezone.
switch dequeueFrom[indexPath.row] {
case .Birthday:
if let pickedBday = pickedBday,
let bday = NSDate.dateFromISOString(pickedBday) {
(cell as! RegisterTextFieldCell).content(bday.longFormattedString())
}
// dateFromISOSString is declared in an extension.swift
class func dateFromComponents(components: NSDateComponents) -> NSDate? {
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
return calendar?.dateFromComponents(components)
}
class func dateFromString(string: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss-SSS"
if let stringDate = dateFormatter.dateFromString(string) {
return stringDate
} else {
return nil
}
}
func ISOStringFromDate() -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
return dateFormatter.stringFromDate(self).stringByAppendingString("Z")
}
class func dateFromISOString(string: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
if let stringDate = dateFormatter.dateFromString(string) {
return stringDate
} else {
return nil
}
}
Any help with how I can make NSDate() be my local timezone so this one day behind issue can go away? Any help is greatly appreciated :)
The problem is in your method ISOStringFromDate because you are getting the local time and manually adding the Z (Z means UTC) to the string. Try like this when creating your iso8601:
extension NSDate {
var iso8601: String {
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return dateFormatter.stringFromDate(self)
}
}
and your code should be:
pickedDate.iso8601 // to get your date iso8601 string

Swift full date with milliseconds

Is any way to print full date with milliseconds?
For example, I'm doing this:
print("\(NSDate())")
But I'm just get this:
2016-05-09 22:07:19 +0000
How can I get the milliseconds too in the full date?
Updated for Swift 3
let d = Date()
let df = DateFormatter()
df.dateFormat = "y-MM-dd H:mm:ss.SSSS"
df.string(from: d) // -> "2016-11-17 17:51:15.1720"
When you have a Date d, you can get the formatted string using a NSDateFormatter. You can also use a formatter to turn a string date based on your format into a Date
See this chart for more on what dateFormat can do http://waracle.net/iphone-nsdateformatter-date-formatting-table/
Swift 5 to/from Timestamp String Extension
extension String {
static func timestamp() -> String {
let dateFMT = DateFormatter()
dateFMT.locale = Locale(identifier: "en_US_POSIX")
dateFMT.dateFormat = "yyyyMMdd'T'HHmmss.SSSS"
let now = Date()
return String(format: "%#", dateFMT.string(from: now))
}
func tad2Date() -> Date? {
let dateFMT = DateFormatter()
dateFMT.locale = Locale(identifier: "en_US_POSIX")
dateFMT.dateFormat = "yyyyMMdd'T'HHmmss.SSSS"
return dateFMT.date(from: self)
}
}

Resources