Why can I not format my NSDate with the specified time zone with NSDateFormatter? - ios

I want to get a date that is represented in a String with a time zone GMT+1 and display it on screen with the local time zone GMT+10.
I have 2 methods, one is for create a date from a String (with GMT+1 timeZone), the other one is to format the date into a String (with localTimeZone GMT+10):
func dateFromString(dateString: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+1")
dateFormatter.dateFormat = "M/d/yyyy hh:mma"
return dateFormatter.dateFromString(dateString)
}
func stringFromDate(date: NSDate) -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone.localTimeZone()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
return dateFormatter.stringFromDate(date)
}
In the playground, when I do this:
let date = dateFromString("4/8/2015 1:29am")!
println(date)
println(stringFromDate(date))
I get the following output on the right side:
"Apr 8, 2015, 1:29 AM"
"2015-04-07 15:29:00 +0000"
"1:29 AM"
I don't understand why I don't get what I am expecting and looking for:
"Apr 8, 2015, 1:29 AM"
"2015-04-08 10:29:00 +0000"
"10:29 AM"
What's wrong?

Input formatters need the time zone in their string. Like so:
func dateFromString(dateString: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/d/yyyy hh:mma z"
return dateFormatter.dateFromString(dateString)
}
let date = dateFromString("4/8/2015 1:29am GMT+01")!
Also note that NSTimeZone names have a two digit offset. Compare in the playground
var oops = NSTimeZone(abbreviation: "GMT+1")
var righteous = NSTimeZone(abbreviation: "GMT+01")
The first is nil, the second is not.

I wouldn't trust the formatting of a time stamp that the debugger prints. In my experience dates are always in UTC regardless of the time zone you set according to the log. Try adding the date as a string to a label on the project and see if it's right.
The reasoning behind this as far as I know is that when you print to the log, all it's doing is calling -description. In the case of NSDate this will return in UTC by definition.

Related

I can't convert iso8601 to string swift

I have a string coming from API and its format will be like this
"2021-03-01T15:00:00+07:00"
so i try to convert this string to date using this code
// string to date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let date = dateFormatter.date(from: isoDate)!
print("date from date Formatter = \(date)")
// convert date back to string
dateFormatter.dateFormat = "EEEE HH:mm"
let dateString = dateFormatter.string(from: date)
print("date string \(dateString)")
return dateString
The result that I expect is -> "2021-03-01 08:00:00 +0000", "Monday 15:00"
When I try this on playground the result is what I want, but when I try this on my project the result is
-> "1478-03-01 08:00:00 +0000", "Sunday 14:42"
How can I change the result to the same as i expect? Thanks
It looks like you are using a different calendar than you expect in your project (buddhist maybe?) and I guess this is because you haven't set one explicitly so it's the one set in System Preferences.
So if you for some reason do not want to use the users current calendar (and locale and time zone) you need to set those properties on your date formatter instance
//Gregorian calendar
dateFormatter.calendar = Calendar.init(identifier: .gregorian)
//UTC time zone
dateFormatter.timeZone = TimeZone(identifier: "UTC")
//English locale
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
This will give you the expected output.
Note that the playground is a bit inconsequent in what it uses and it seems to be a mix of what we have set in our System preferences and hardcoded values.

iOS Swift: how to convert specific date string format to Date object, when string contains time zone abbreviation?

I am getting a date string from server in the format of "March 08, 2018 16:00:00 PST" where there is a lot of whitespace between Month & Date.
My intention is to basically remove those extra whitespaces. My idea is that- I will convert the string into Date object, and then convert back to string.
How can I convert this into Date object using Date Formatter, taking timezone into consideration.
I am concerned about the "PST" here. While converting the Date to String, I will need in the format - "March 08, 2018 16:00:00 PST" i.e. PST (or whatever time zone comes in) should stay intact in the final string.
extension String {
func getDate(fromFormat format: String = "MMMM dd, yyyy HH:mm:ss zzz") -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
return dateFormatter.date(from: self)
}
}
let myDateString = "March 08, 2018 16:00:00 PST"
myDateString.getDate()
You can call with other time formats too.
Try this
let isoDate = "March 08, 2018 16:00:00 PST"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM dd, yyyy HH:mm:ss z"
let date = dateFormatter.date(from: isoDate)!
Try this
class func stringToDate (dateString:String, dateFormat:String) -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateFormat
let dateFromString = dateFormatter.date(from: dateString)
return dateFromString
}

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
}

GMT date string getting converted to UTC Date

**
GET GMT DATE STRING
**
func getGMTString(dateAsDate:NSDate) -> String
{
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"//this your string date format
// dateFormatter.locale = NSLocale.currentLocale()
// dateFormatter.timeZone = NSTimeZone(name: "GMT")
let date = dateFormatter.stringFromDate(dateAsDate)
return date
}
OUTPUT
startDate---2016-06-29 00:00:00 GMT+5:30
endDate----2016-06-30 03:57:39 GMT+5:30
NOW TRYING to get GMT Date object from output string
func getGMTDate(string:String) -> NSDate {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"//this your string date format
// dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT")!
// dateFormatter.locale = NSLocale.currentLocale()
let date = dateFormatter.dateFromString(string)
return date!
}
PROBLEM: OUTPUT DATE OBJECT MESS
startDateOBJECT---2016-06-28 18:30:00 +0000 endDateOBJECT----2016-06-30 17:30:00 +0000
Unable to figure what is going wrong
I don't understand your step 3. I looks like you're using NSLog or a Swift print to display the resulting date. That is ALWAYS done in UTC.
If you want to view your date in a different format, or with your local time zone, you need a second date formatter to convert the NSDate to an output date string.
Here's the flow:
input date string -> input date formatter -> NSDate
NSDate -> output date formatter -> display date in local time zone

Date string to NSDate swift

i'm having an array fill with date string, which i would like to go through and check whether the date is today or yesterday. The date string could look like following:
2015-04-10 22:07:00
So far i've tried just to convert it using dateFormatter, but it keeps returning nil
var dateString = arrayNews[0][0].date as NSString
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
var date = dateFormatter.dateFromString(dateString as String)
println(date)
the sudo code i would like to look something like this
if dateString == currentDate
date = "Today, hh:mm"
else if dateString == currentDate(-1)
date = "Yesterday, hh:mm
else
date = dd. MM, hh:mm
in the else statement the date could be 1. April, 12:00
How can i achieve such a logic?
Without the logic
func getDate(dateStr:String, format:String = "yyyy-MM-dd HH:mm:ss") -> NSString {
var dateFmt = NSDateFormatter()
dateFmt.timeZone = NSTimeZone.defaultTimeZone()
dateFmt.dateFormat = format
let newsDate = dateFmt.dateFromString(dateStr)!
let date = NSDate();
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone()
let localDate = dateFormatter.stringFromDate(date)
return ""
}
You have to use yyyy-MM-dd HH:mm:ss instead of yyyy-MM-dd hh:mm:ss
HH: 24h format
hh: 12h format (with AM/PM)
Pay attention with dateFormatter, by default, it use localtime zone.
println() shows the value for GMT time, which is hold by NSDate.
It means, without specifying timezone, when you convert your string 2015-04-10 22:07:00 to NSDatetime, it return a data which is the time at your local time zone is 2015-04-10 22:07:00. As NSDate holds date time in GMT, you will see a different value when you show the value of that NSDate with println().
If your timezone is GMT+2 (2h earlier than GMT), when it's 22h:07 in your place, the GMT time is 20h:07. When you call println() on that NSDate, you see 2015-04-10 20:07:00
To compare 2 NSDate:
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
let compareResult = calendar?.compareDate(date, toDate: date2, toUnitGranularity: NSCalendarUnit.CalendarUnitDay)
if (compareResult == NSComparisonResult.OrderedSame) {
println("yes")
} else {
println("no")
}
//to get yesterday, using NSCalendar:
let yesterday = calendar?.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: -1, toDate: date, options: NSCalendarOptions.MatchStrictly)

Resources