Issue in formatting date string Swift 3 [duplicate] - ios

This question already has answers here:
NSDateFormatter doesn't show time zone abbreviation for "Asia/Kolkata" for the "z" or "zzz" specifier, just the GMT offset
(1 answer)
What is the best way to deal with the NSDateFormatter locale "feature"?
(4 answers)
Closed 5 years ago.
I need to convert the following date string in to a Date in Swift 3.
Fri Dec 09 16:18:43 AMST 2016
Here is the code that i have been using, but it's getting cash on this particular date string conversion. (This date was logged on Android using new Date().toString() method.)
static func formatDate(date: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
dateFormatter.dateFormat = "EEE MMM dd HH:mm:ss zzz yyyy"
//Works for "Fri Sep 16 10:55:48 GMT+05:30 2016"
var myDate = dateFormatter.date(from: date)
// My date returns nil on "Fri Dec 09 16:18:43 AMST 2016"
dateFormatter.dateFormat = "dd/MM/yyyy"
return "\(dateFormatter.string(from: myDate!))"
}
There are both type of strings in the database. I tried with various types of Timezone formats (z/zz/zzz/zzzz/zzzzz) but always myDate returns nil.
Any help would be appreciated.
Thanks In Advance.

Apple doc for TimeZone(abbreviation:):
In general, you are discouraged from using abbreviations except for unique instances such as “GMT”. Time Zone abbreviations are not standardized and so a given abbreviation may have multiple meanings.
Does AMST represents "Amazon Summer Time" (UTC-3) or "Armenia Summer Time" (UTC+5)? See: https://www.timeanddate.com/time/zones
That's probably why it can't detect the proper timezone to use.
Solutions I can propose:
If you know which timezone AMST is:
replace AMST by UTC-3 or UTC+5 in the date string
remove AMST from the date string and use dateFormatter.timeZone = TimeZone(secondsFromGMT: -3 or 5 * 3600)
Have your source output a more precise timezone.
Note the following code, where AMST is understood correctly:
let df = DateFormatter()
df.locale = Locale.init(identifier: "pt_BR") // assuming AMST is Amazon Summer Time (UTC -3)
df.dateFormat = "HH:mm:ss z"
print(df.date(from: "16:18:43 AMST")) // Optional(2000-01-01 19:18:43 +0000)
But as soon as you include English day or month names (e.g. Fri or Dec) it will produce nil (because they aren't in Portuguese).

Related

Swift date formatter ignoring months

I wrote a date reformatter but it appears Swift's date formatter itself is ignoring the months. The documentation says this shouldn't be happening. How do I make it not ignore months?
let testDate:String = "2020-11-22-11:00"
print("start date: ",testDate," reformatted date: ", reformatDate(dateString: testDate))
func reformatDate(dateString: String) -> String? {
print("dateString: ",dateString)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-DD-HH:mm"
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
return dateFormatter.string(from: dateString)
}
this prints:
start date: 2020-11-22-11:00 converted date: 22-01-2020 11:00 AM
It unreasonably turns all months to 1!
Your format string is incorrect. It should be:
yyyy-MM-dd-HH:mm
and
dd-MM-yyyy h:mm a
dd means day-of-month, whereas DD means day-of-year.
Note that you should also do:
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
whenever you are using a custom date format.
Parsing 2020-11-22-11:00 with yyyy-MM-DD-HH:mm means that you want the twenty second day of the year 2020, in the month November. That makes no sense, and DateFormatter ends up ignoring the month because apparently day-of-year is a "stronger" date component. The 22nd day of any year is the 22nd of January.
Then, when you format the parsed date with DD-MM-yyyy h:mm a, the month component gets displayed as 01, and the day-of-year is still displayed as 22.
Here are some useful links to learn about format specifiers, you'll just how much lowercase/uppercase matters.
NSDateFormatter.com
TR-35

Display local time zone abbreviation using DateFormatter

I have a DateFormatter that outputs the date in the format "2:00pm, Thu 18 Oct":
static func scheduleFormatter() -> DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.amSymbol = "am"
dateFormatter.pmSymbol = "pm"
dateFormatter.dateFormat = "h:mma, EE dd MMM"
return dateFormatter
}
I need to add in the local time zone abbreviation of the user so that the string appears like "2:00 pm GMT, Thu 18 Oct". How can I do that?
Look at the Unicode Date Formatting Patterns:
Probably you want the pattern v:
The short generic non-location format. Where that is unavailable, falls back to the generic location format ("VVVV"), then the short localized GMT format as the final fallback.
or z:
The short specific non-location format. Where that is unavailable, falls back to the short localized GMT format ("O").
Note that time zone names are connected to language and setting posix locale will probably break that.
You could also ask for the abbreviation directly and include it in your format explicitly:
"h:mma, '\(TimeZone.current.abbreviation() ?? "")' EE dd MMM"
To display the time zone you can simply add "zzz" in your dateFormat string. For example: "h:mma zzz, EE dd MMM"
public static Date getCurrentTimeStampDate(){
String currentDate = new SimpleDateFormat(""yyyy:MM:dd HH:mm:ss").format(Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime());
SimpleDateFormat formater = new SimpleDateFormat(""yyyy:MM:dd HH:mm:ss");
try {
return formater.parse(currentDate);
} catch (ParseException e) {
return null;
}
}

Formatting a date from a string in swift [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 have the following date coming from a server 2019-09-05T10:37:49.494Z as a string and i need to parse this and convert it to a format like this Fri September 13,2019 12:36 AM and back to a string again:
i found multiple question links but none of them are working for me Question One
Question Two
it tried doing this:
let dateFormatterGet = DateFormatter()
let dateFormatterPrint = DateFormatter()
var rawDate = "2019-09-05T10:37:49.494Z"
dateFormatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
dateFormatterPrint.dateFormat = "E, d MMM yyyy HH:mm"
var formattedDate = "Error Formatting date"
if let date = dateFormatterGet.date(from: rawDate) {
formattedDate = dateFormatterPrint.string(from: date)
print("Formatted Date : \(formattedDate)")
}else {
print("There was an error decoding the string")
}
this fails printing the error message, what am i doing wrong and how can i fix it?
You are almost there.
A small tip playing with (NS)DateFormatter put the dateFormat above/under the date string.
yyyy-MM-dd'T'HH:mm:ssZ
2019-09-05T10:37:49.494Z
Then, add "spaces" to align and separate them.
yyyy - MM - dd 'T' HH : mm : ss Z
2019 - 09 - 05 T 10 : 37 : 49 . 494Z
^ ^^^
I highlighted the missing ones. You need to tell the (NS)DateFormatter through the dateFormat how to interpret theses additional characters.
Let's check the documentation.
It's
Fractional Second - truncates (like other time fields) to the count of letters. (example shows display using pattern SSSS for seconds value 12.34567)
So using yyyy-MM-dd'T'HH:mm:ss.SSSZ should interpret them and fix your issue.
That's how you fix your issue. And it explained your error.
But since as pointed by #Zombie it's using a ISO format, use if available the ISO8601DateFormatter if possible (iOS10+)
If in future cases you don't have an ISO something format, you can use theses tips ;)
The format you provided seems like an iso 8601 date for this reason I would suggest using the ISO8601DateFormatter
You can specify the options to match your string
here is an example
let dateString = "2019-09-05T10:37:49.494Z"
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [
.withDashSeparatorInDate,
.withFullDate,
.withFullTime,
.withFractionalSeconds,
.withColonSeparatorInTime
]
// "Sep 5, 2019 at 12:37 PM"
let date = formatter.date(from: dateString) ?? Date()
//"Thursday, September 5, 2019 at 12:37:49 PM"
let formattedDate = DateFormatter.localizedString(
from: date,
dateStyle: .full,
timeStyle: .medium
)
The problem is you don't tell dateFormatterGet how to parse milliseconds. Modify the dateFormat to:
dateFormatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

Convert two strings to NSDate

i am trying to calculate the time between two dates. One of the dates is today and the other date is somewhere in the future.
The issue is the date in future is separated into two string, the first containing the date and the other containing the time for that date. When i put the two strings together to a single string and try to convert it to a NSDate i get Nil.
I assume there is something wrong with my date variable.
let eventDate: String? = "21 Aug Sun 2016"
let eventTime: String? = "9:00 PM"
let date : String? = "\(eventDate!) \(eventTime!)"
print(date!) // "21 Aug Sun 2016 9:00 PM"
let formatter = NSDateFormatter()
formatter.dateFormat = "dd MMM eee yyyy HH:MM a"
formatter.AMSymbol = "AM"
formatter.PMSymbol = "PM"
if let dateTimeForEvent = formatter.dateFromString(date!) {
print(dateTimeForEvent)
}else {
print("Error")// prints error
}
Two things:
You have the wrong format for the time. It should be h:mm a. HH is for a two-digit, 24-hour hour. You have a 1 or 2 digit, 12-hour hour. And MM is for a 2-digit month. Use mm for a two-digit minute.
If your date and time strings will always be in English, you need to set the formatter's locale to an English locale. If you don't, your code will always return a nil date on any device using a language other than English.
Your primary issue is that you're using HH, which is for 24-hour time, instead of hh, and MM (which is for month) instead of mm. Try this:
import Foundation
let eventDate = "21 Aug Sun 2016"
let eventTime = "9:00 PM"
let eventDateTime = "\(eventDate) \(eventTime)"
print(eventDateTime) // "21 Aug Sun 2016 9:00 PM"
let formatter = NSDateFormatter()
formatter.dateFormat = "dd MMM eee yyyy hh:mm a"
if let date = formatter.dateFromString(eventDateTime) {
print(date) // 2016-08-21 21:00:00 +0000
}
else {
print("Error")// prints error, no shit? why is this comment here?
}
Side notes:
Why is a variable called date, if it's a String??
Why is date an optional, anyway? You assigned it a literal value.
You don't have to set the AMSymbol and the PMSymbol. Those only pertain to printing dates, not parsing them.

Converting String to NSDate Giving Wrong Date

I have a String that I converted using stringFromDate and now I'm trying to convert it back, however when the UIPicker starts, it's giving me the wrong day
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MMM YYYY"
print(birthday) // logs 15 Jan 1992
let date = dateFormatter.dateFromString(birthday)
self.datePicker.setDate(date!, animated: true)
I tried hardcoding "15 Feb 1992" but still the same result. The date on UIDatePicker shows 22 Dec 1991 on Start.
If I use hardcore 10 Jan 1980, it starts from 23 December 1979.
(I don't know if that's the case but I have MMM dd YYYY in UIPickerView whereas it's dd MMM YYYY for the strings.. I don't think though because while saving, it saves the right value)..
To use correct format string is most important..
YYYY is week-based calendar year. (used in ISO week-year calendar)
yyyy is ordinary calendar year.
so, You should use 'yyyy' instead of 'YYYY'.
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
print(birthday)
let date = dateFormatter.dateFromString(birthday)
self.datePicker.setDate(date!, animated: true)
For more string format for Date: refer this link
https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
You are using the wrong format. You need dd MMM yyyy.

Resources