Issue when converting a date string of format "yyyy-MM-dd HH:mm:ss.m" to "yyyy-MM-dd HH:mm:ss" - ios

I'm working on an iOS project in swift 5. In one of my API, the date is coming in the format, "yyyy-MM-dd HH:mm:ss.m". And from this date, I need to fetch the time. But the issue is, suppose the date I'm getting from API is "1900-01-01 08:30:00.000000", and when I convert this date format to YYYY-MM-dd HH:mm:ss, the result is coming as "1900-01-01 08:00:00", the time before conversion is 08:30:00.000000 but after conversion 08:00:00. Why it is happening? Please help me.
I will add my code here,
let dateTime = "1900-01-01 08:30:00.000000"
let outFormatter = DateFormatter()
outFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.m"
if let date = outFormatter.date(from: dateTime) {
//here value od date is 1900-01-01 04:18:48 +0000
outFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
outFormatter.locale = tempLocale
let exactDate = outFormatter.string(from: date)
//here the value of exactDate is 1900-01-01 08:00:00
}

m is minutes and S is milliseconds so the format must be "yyyy-MM-dd HH:mm:ss.S".
Further for fixed date formats it's highly recommended to set the locale to en_US_POSIX
let dateTime = "1900-01-01 08:30:00.000000"
let outFormatter = DateFormatter()
outFormatter.locale = Locale(identifier: "en_US_POSIX")
outFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.S"
if let date = outFormatter.date(from: dateTime) {
//here value od date is 1900-01-01 04:18:48 +0000
outFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let exactDate = outFormatter.string(from: date)
//here the value of exactDate is 1900-01-01 08:00:00
}
But if you only want to strip the milliseconds from the date string there is a simpler solution
let dateTime = "1900-01-01 08:30:00.000000"
let exactDate = dateTime.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
It removes the dot and any digit behind

Related

Get only time from Date

How to get only time from the date with am/pm. Below is my code what I have tried so far:
func changeFormat(str:String) -> String {
let dateFormatter = DateFormatter()
let newDateFormatter = DateFormatter()
// step 1
dateFormatter.dateFormat = "MM/dd/yyyy HH:mm aa" // input format
newDateFormatter.dateFormat = "HH:mm aa" // output format
let date = dateFormatter.date(from: str)!
// step 2
let string = newDateFormatter.string(from: date)
return string
}
Usage:
let strTimeFromDate = changeFormat(str: self.response?.Data[indexPath.row].ADateTime ?? "")
input date:
06/22/2021 2:00 PM
output:
12:45 PM
Getting wrong time return after formatting. Please guide what's wrong with above code
As mentioned by #JoakimDanielson in the comment, you are mixing HH (24 hours format) with hh (12 hours format). Using hh for the dateFormatter (given your input has 02:00 PM) should fix your issue (as long as this input value was captured in the same time zone in which you intend to convert).
In case you are still seeing that the output is not expected, then it is the issue with missing timeZone info in your input. You are trying to convert String > Date > String without specifying an input timeZone & output timeZone. You can try printing these values in your implementation.
print("dateFormatter.timeZone.secondsFromGMT() : \(dateFormatter.timeZone.secondsFromGMT())")
let date = dateFormatter.date(from: str)!
print("parsed date : \(date)")
print("\n ------------------------ \n")
// step 2
print("newDateFormatter.timeZone.secondsFromGMT() : \(newDateFormatter.timeZone.secondsFromGMT())")
let string = newDateFormatter.string(from: date)
print("parsed string : \(string)")
For me it prints following. 19800 / (60 * 60) = 5.5 (+05:30)
dateFormatter.timeZone.secondsFromGMT() : 19800
parsed date : 2021-06-22 06:30:00 +0000
------------------------
newDateFormatter.timeZone.secondsFromGMT() : 19800
parsed string : 12:00 PM
The issue is - for these two conversions to happen correctly - you must specify an appropriate time zone.
String to Date
Date to String
Here's what that implementation could look like. Assuming input is "06/22/2021 2:00 PM +0530"
func changeFormat(str: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(secondsFromGMT: Int(5.5*60*60)) // +05:30
let newDateFormatter = DateFormatter()
newDateFormatter.timeZone = TimeZone(secondsFromGMT: Int(5.5*60*60)) // +05:30
dateFormatter.dateFormat = "MM/dd/yyyy hh:mm aa Z"
newDateFormatter.dateFormat = "hh:mm aa"
let date = dateFormatter.date(from: str)!
let string = newDateFormatter.string(from: date)
return string
}
When you are consuming this date string from your backend server, you should consider using appropriate time zone for it. An example, assuming input is "06/22/2021 2:00 PM +0000" -
func changeFormat(str: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // Server timeZone (UTC)
let newDateFormatter = DateFormatter()
newDateFormatter.timeZone = TimeZone.current // User's timeZone
dateFormatter.dateFormat = "MM/dd/yyyy hh:mm aa Z"
newDateFormatter.dateFormat = "hh:mm aa"
let date = dateFormatter.date(from: str)!
let string = newDateFormatter.string(from: date)
return string
}
"HH" is for 24h format and "aa" is for 12h format so you can't mix them, so you should use "hh:mm a" instead for both DateTimeFormatter's

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
}

dateFormatter returns wrong date with two digit year specifier [duplicate]

For date Input "00/02/02"
formating Style is yy/MM/dd
I am getting correct output like 02/01/2000
But issue is when trying with "00/01/01"
getting output like this '01/01/12100'
But I don't know why this year coming like 12100
My code is
let str = "00/01/01"
let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yy/MM/dd"
if let showDate = inputFormatter.date(from: str) {
inputFormatter.dateFormat = "dd/MM/yyyy"
let resultString = inputFormatter.string(from: showDate)
print(resultString)
}
year input type always as yy format.
As per the #MartinR suggestion
settinginputFormatter.defaultDate to current date or Date(timeIntervalSinceReferenceDate: 0) its worked fine
let str = "00/01/01"
let inputFormatter = DateFormatter()
inputFormatter.defaultDate = Date(timeIntervalSinceReferenceDate: 0)
inputFormatter.dateFormat = "yy/MM/dd"
if let showDate = inputFormatter.date(from: str) {
inputFormatter.dateFormat = "dd/MM/yyyy"
let resultString = inputFormatter.string(from: showDate)
print(resultString)
}
I managed to reproduce this bug by setting the timezone of the formatter, before getting the date from it, to your local timezone:
inputFormatter.timeZone = TimeZone(identifier: "Asia/Kolkata")
//Or
inputFormatter.timeZone = TimeZone(identifier: "Asia/Calcutta")
They both lead to 01/01/12100.
Actually, using a date format of yy/MM/dd hh:mm:ss, all dates starting from 00/01/01 00:00:00 to 00/01/01 05:29:59 give a year component of 12100. This is due to the time zone of Kolkata being offset by +05H30 from GMT. This is a bug.
Setting the timezone to UTC yields the desired output:
inputFormatter.timeZone = TimeZone(identifier: "UTC") //01/01/2000
This bug occurs with other timezones too:
inputFormatter.timeZone = TimeZone(identifier: "Africa/Addis_Ababa")
inputFormatter.timeZone = TimeZone(identifier: "Europe/Moscow")
inputFormatter.timeZone = TimeZone(identifier: "Asia/Hong_Kong")
Basically all timezones that have GMT + hh:mm

dateFromString() returning wrong date swift 3.0

i am passing "01/12/2017" in the fromDate.text(textfield), but receiving unexpected output.
let formatter = DateFormatter.init()
formatter.dateFormat = "dd/mm/yyyy"
startDate = formatter.date(from: fromDate.text!)
print("startDate = \(startDate)")
output is : 31/12/2016
The format of date should be dd/MM/yyyy not dd/mm/yyyy. The mm indicates the minutes and MM indicates the month.
And also add the below line in your code
formatter.timeZone = TimeZone(abbreviation: "GMT+0:00")
This line of code set time zone. If you not, then you get 30/11/2017 in output.
The reason behind this is when string date not contain time then formatter assume that it is midnight and you also not given the timezone so it will take current timezone.
It has to be dd/MM/yyyy dateformat. MM in capital.
func convertToString(of dateTo: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy" //Your New Date format as per requirement change it own
let newDate: String = dateFormatter.string(from: dateTo) //pass Date here
print(newDate) //New formatted Date string
return newDate
}

Format String to HH:mm in Swift

My code:
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = dateFormatter.dateFromString("2015-09-01 00-32-40")
Result: 2015-08-31 17:32:40
But I want get result like this: 17:32. How do I resolve it?
If you're trying to get an NSDate and not a string representation, printing the NSDate will always show the full date time. To just show the hours and minutes, you'll have to create a string representation using an "HH:mm" date format, ex:
// Your original code
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = dateFormatter.dateFromString("2015-09-01 00-32-40")
// To convert the date into an HH:mm format
dateFormatter.dateFormat = "HH:mm"
let dateString = dateFormatter.stringFromDate(date!)
println(dateString)
Not sure why you're looking to get a result of "17:32", but this will produce "00:32" as a result from the original "00-32" portion of the string.

Resources