How to get time from JSON string using Swift? - ios

I tried from my end and browsed too. Might be this question have been asked many times. I parsed weather response of city's (ex: Mar del Plata) based on there timezone. I want time in HH:mm format. Below is the sample JSON response.
"sunrise": "2016-07-10T08:05:02-0300", "sunset": "2016-07-10T17:46:29-0300"
My code:
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ"
dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
guard let date = dateFormatter.dateFromString(dateString) else {
assert(false, "no date from string")
}
dateFormatter.dateFormat = "HH:mm"
//dateFormatter.timeZone = NSTimeZone(name: "UTC")
return dateFormatter.stringFromDate(date)
Whenever I print or display date string in label the hours is getting changed. I WANT exact time coming in response.
My temporary solution for the above is
// Begin - Its a temperory solution
if dateString.contains("T") {
print("dateString.contains(T)")
let myArray = dateString.componentsSeparatedByString("T")
if myArray.count > 0 {
let str = myArray[1]
if str.contains("+") {
print("(str.contains(+))")
let myArr = str.componentsSeparatedByString("+")
if myArr.count > 0 {
let str1 = myArr[0]
if str1.contains(":") {
print("str1.contains(:)")
let myAr = str1.componentsSeparatedByString(":")
if myAr.count > 0 {
let str2 = myAr[0]
let str3 = myAr[1]
let str4 = "\(str2):\(str3)"
print(str4)
return str4
}
//print(myAr)
}
}
}
if str.contains("-") {
print("(str.contains(-))")
let myArr = str.componentsSeparatedByString("-")
if myArr.count > 0 {
let str1 = myArr[0]
if str1.contains(":") {
print("str1.contains(:)")
let myAr = str1.componentsSeparatedByString(":")
if myAr.count > 0 {
let str2 = myAr[0]
let str3 = myAr[1]
let str4 = "\(str2):\(str3)"
print(str4)
return str4
}
//print(myAr)
}
}
}
}
}
// End - Its a temporary solution
I want a better solution instead of my temporary one.
Edit1:
As I mentioned, I want same time coming in JSON response by discarding the timezone.
Please suggest me and guide me how to deal with time zone in future. Hope you guys understand, what am I upto. Sorry for my poor English.
Thanks in Advance.

If you absolutely don't care about the timezone, you can simply trim it off:
let sunrise = "2016-07-10T08:05:02-0300"
let sunriseNoTimezone = sunrise.substringToIndex(sunrise.endIndex.advancedBy(-5))
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
let date = formatter.dateFromString(sunriseNoTimezone)
print(date)

Try below line of code. Hope it will help you...
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ"
dateFormatter.timeZone = NSTimeZone.systemTimeZone()
guard let date = dateFormatter.dateFromString(dateString)
else {
assert(false, "no date from string")
}
dateFormatter.dateFormat = "HH:mm"
return dateFormatter.stringFromDate(date)

Related

iOS Get Time Zone String Without DST Offset

I am looking for a list of timezones but when try to generate that I get the DST offset added to it. But I want the standard time, not the one with DST.
Here is the code I am using. For Denmark, I am getting GMT+2 instead of GMT+1
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .long
dateFormatter.dateFormat = "ZZZZ"
let list = TimeZone.knownTimeZoneIdentifiers
for (i, city) in list.enumerated() {
let timezone = TimeZone(identifier: city)
dateFormatter.timeZone = timezone
var isSupportDST = false
if timezone?.nextDaylightSavingTimeTransition != nil {
isSupportDST = true
}
let date = Date()
var timezoneString = dateFormatter.string(from: date)
if timezoneString.count > 3 {
timezoneString.insert(" ", at: timezoneString.index(timezoneString.startIndex, offsetBy: 3))
}
if timezoneString.count > 5 {
timezoneString.insert(" ", at: timezoneString.index(timezoneString.startIndex, offsetBy: 5))
}
var formattedCityName = city
formattedCityName = city.replacingOccurrences(of: "_", with: " ")
var dstoffset = 0 as TimeInterval
if let offset = timezone?.daylightSavingTimeOffset(){
dstoffset = offset
}
let cityWithTimezone = CityWithTimeZone(city: formattedCityName, timeZoneString: timezoneString, timeZoneInSeconds: timezone?.secondsFromGMT() ?? 0, dstOffset: dstoffset, isDSTSupport: isSupportDST)
cityList.insert(cityWithTimezone, at:i)
}
Please try to set the timezone of the formatter like this
let timezone = TimeZone(identifier: city)
dateFormatter.timeZone = TimeZone(secondsFromGMT: TimeZone.current.secondsFromGMT())
It will set the current time properly.

How to check if the current string is in 24 hour format time or 12 hour format time in swift3?

I am getting a particular string from the web service which is actually a time. So I want to check whether the string which i get from web service is in 24 hour format. I have successfully appended AM and Pm with this code:
let dateAsString = "13:15"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
let date = dateFormatter.date(from: dateAsString)
dateFormatter.dateFormat = "h:mm a"
let Date12 = dateFormatter.string(from: date!)
print("12 hour formatted Date:",Date12)
But i wish to know whether "13:15" is greater than "12:00" as this time i am getting from webservice.
Just pass the 12-hour date format and check for nil
let dateAsString = "13:15"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm"
let is24HourFormat = dateFormatter.date(from: dateAsString) == nil
What you did is just formatting date to nice readable string..
But what you actually looking for is comparing between dates:
See next example for comparing two dates [Swift 3.1]
func compareDates() {
let date1 = Date() // now
let date2 = Date().addingTimeInterval(20) // now+20secodns
switch date1.compare(date2) // return ComparisonResult
{
case .orderedAscending:
print("date1 < date2")
case .orderedDescending:
print("date1 > date2")
case .orderedSame:
print("date1 == date2")
}
}
And if you want to compare just times that you have already in 24h format and strings, you could just use normal comparison for strings but I don't recommend this
/// compare only times in 24h format in strings
func compareTimesInStrings() {
let time1 = "13:00"
let time2 = "09:05"
if time1 < time2 {
print("time1 < time2")
} else if time1 > time2 {
print("time1 > time2")
} else {
print("time1 == time2")
}
}
May be this is a long answer. But here is the another way :
let dateAsString = "13:15"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
if let date = dateFormatter.date(from: dateAsString) {
dateFormatter.dateFormat = "h:mm a"
let Date12 = dateFormatter.string(from: date)
let amRange = Date12.range(of: dateFormatter.amSymbol)
let pmRange = Date12.range(of: dateFormatter.pmSymbol)
if pmRange == nil {
print("12 hours")
} else if amRange == nil {
print("24 hours")
}
} else {
print("not in the time range") // if dateAsString is > 23:59
}

How to format date in Swift that similarly matches Json?

I am having trouble generating Date objects that match the json output. In http://chartapi.finance.yahoo.com/instrument/1.0/aapl/chartdata;type=quote;range=1y/json - the dates are in the following format "Date": 20151013. In order to get 2015-10-13, first I use Alamofire & SwiftJSON in my API call and JSON parsing. Here are some relevant lines from my code:
let dateInteger = subJson["Date"].int
if dateInteger != nil {
let editedDateInt = dateInteger!
let dateString = NSMutableString(string: "\(editedDateInt)")
dateString.insert("-", at: 4)
dateString.insert("-", at: 7)
chartpoint.date = Formatters.sharedInstance.dateFromString(key: dateString as String) }
// date extension
public class Formatters {
public static let sharedInstance = Formatters()
private let dateKeyFormatter = DateFormatter()
init() { dateKeyFormatter.dateFormat = "yyyy-MM-dd" }
public func dateFromString(key: String?) -> Date? {
guard let key = key else { return nil }
return dateKeyFormatter.date(from: key) }
Problem is the output came up Optional(2015-10-12 16:00:00 +0000). Not quite 2015-10-13 that I was expecting. How do I fix this? Is this related to user's Locale or TimeZone?
Check this out
Swift 3.0
let dateFromServer = "20151013"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
let date = dateFormatter.date(from: dateFromServer)
dateFormatter.dateFormat = "yyyy-MM-dd"
let finalDate = dateFormatter.string(from: date!)
print(finalDate)
Output:
2015-10-13
As suggested by #rmaddy changed the format style form YYYY to yyyy.

timeIntervalSinceDate returns the wrong value

I have two functions.
The first is writing NSDate() to NSUserDefaults as a string.
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss.SSSSxxx"
let dateString = dateFormatter.stringFromDate(NSDate())
NSUserDefaults.standardUserDefaults().setObject(dateString, forKey: "lastDate")
NSUserDefaults.standardUserDefaults().synchronize()
The second one is reading this value, converting it to NSDate and comparing with the current time and date.
let dateString = try NSUserDefaults.standardUserDefaults().stringForKey("lastDate")
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss.SSSSxxx"
if dateString != nil {
let date = try dateFormatter.dateFromString(dateString!)
if date != nil {
let interval = NSDate().timeIntervalSinceDate(date!)
let interval2 = Int(interval)
print(interval2)
}
} else {
//some code here
}
The thing is, it returns not 5 seconds (as it should, for example) but something like 43295 or 44592. I logged dates and strings and they seemed fine. Where did I break things?

Swift convert unix time to date and time

My current code:
if let var timeResult = (jsonResult["dt"] as? Double) {
timeResult = NSDate().timeIntervalSince1970
println(timeResult)
println(NSDate())
}
The results:
println(timeResult) = 1415639000.67457
println(NSDate()) = 2014-11-10 17:03:20 +0000 was just to test to see what NSDate was providing.
I want the first to look like the last. The value for dt = 1415637900.
Also, how can I adjust to time zone? Running on iOS.
You can get a date with that value by using the NSDate(withTimeIntervalSince1970:) initializer:
let date = NSDate(timeIntervalSince1970: 1415637900)
To get the date to show as the current time zone I used the following.
if let timeResult = (jsonResult["dt"] as? Double) {
let date = NSDate(timeIntervalSince1970: timeResult)
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.MediumStyle //Set time style
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle //Set date style
dateFormatter.timeZone = NSTimeZone()
let localDate = dateFormatter.stringFromDate(date)
}
Swift 3.0 Version
if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = self.timeZone
let localDate = dateFormatter.string(from: date)
}
Swift 5
if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = .current
let localDate = dateFormatter.string(from: date)
}
It's simple to convert the Unix timestamp into the desired format. Lets suppose _ts is the Unix timestamp in long
let date = NSDate(timeIntervalSince1970: _ts)
let dayTimePeriodFormatter = NSDateFormatter()
dayTimePeriodFormatter.dateFormat = "MMM dd YYYY hh:mm a"
let dateString = dayTimePeriodFormatter.stringFromDate(date)
print( " _ts value is \(_ts)")
print( " _ts value is \(dateString)")
For managing dates in Swift 3 I ended up with this helper function:
extension Double {
func getDateStringFromUTC() -> String {
let date = Date(timeIntervalSince1970: self)
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.dateStyle = .medium
return dateFormatter.string(from: date)
}
}
This way it easy to use whenever you need it - in my case it was converting a string:
("1481721300" as! Double).getDateStringFromUTC() // "Dec 14, 2016"
Reference the DateFormatter docs for more details on formatting (Note that some of the examples are out of date)
I found this article to be very helpful as well
Here is a working Swift 3 solution from one of my apps.
/**
*
* Convert unix time to human readable time. Return empty string if unixtime
* argument is 0. Note that EMPTY_STRING = ""
*
* #param unixdate the time in unix format, e.g. 1482505225
* #param timezone the user's time zone, e.g. EST, PST
* #return the date and time converted into human readable String format
*
**/
private func getDate(unixdate: Int, timezone: String) -> String {
if unixdate == 0 {return EMPTY_STRING}
let date = NSDate(timeIntervalSince1970: TimeInterval(unixdate))
let dayTimePeriodFormatter = DateFormatter()
dayTimePeriodFormatter.dateFormat = "MMM dd YYYY hh:mm a"
dayTimePeriodFormatter.timeZone = NSTimeZone(name: timezone) as TimeZone!
let dateString = dayTimePeriodFormatter.string(from: date as Date)
return "Updated: \(dateString)"
}
func timeStringFromUnixTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
// Returns date formatted as 12 hour time.
dateFormatter.dateFormat = "hh:mm a"
return dateFormatter.stringFromDate(date)
}
func dayStringFromTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
dateFormatter.locale = NSLocale(localeIdentifier: NSLocale.currentLocale().localeIdentifier)
dateFormatter.dateFormat = "EEEE"
return dateFormatter.stringFromDate(date)
}
In Swift 5
Using this implementation you just have to give epoch time as a parameter and you will the output as (1 second ago, 2 minutes ago, and so on).
func setTimestamp(epochTime: String) -> String {
let currentDate = Date()
let epochDate = Date(timeIntervalSince1970: TimeInterval(epochTime) as! TimeInterval)
let calendar = Calendar.current
let currentDay = calendar.component(.day, from: currentDate)
let currentHour = calendar.component(.hour, from: currentDate)
let currentMinutes = calendar.component(.minute, from: currentDate)
let currentSeconds = calendar.component(.second, from: currentDate)
let epochDay = calendar.component(.day, from: epochDate)
let epochMonth = calendar.component(.month, from: epochDate)
let epochYear = calendar.component(.year, from: epochDate)
let epochHour = calendar.component(.hour, from: epochDate)
let epochMinutes = calendar.component(.minute, from: epochDate)
let epochSeconds = calendar.component(.second, from: epochDate)
if (currentDay - epochDay < 30) {
if (currentDay == epochDay) {
if (currentHour - epochHour == 0) {
if (currentMinutes - epochMinutes == 0) {
if (currentSeconds - epochSeconds <= 1) {
return String(currentSeconds - epochSeconds) + " second ago"
} else {
return String(currentSeconds - epochSeconds) + " seconds ago"
}
} else if (currentMinutes - epochMinutes <= 1) {
return String(currentMinutes - epochMinutes) + " minute ago"
} else {
return String(currentMinutes - epochMinutes) + " minutes ago"
}
} else if (currentHour - epochHour <= 1) {
return String(currentHour - epochHour) + " hour ago"
} else {
return String(currentHour - epochHour) + " hours ago"
}
} else if (currentDay - epochDay <= 1) {
return String(currentDay - epochDay) + " day ago"
} else {
return String(currentDay - epochDay) + " days ago"
}
} else {
return String(epochDay) + " " + getMonthNameFromInt(month: epochMonth) + " " + String(epochYear)
}
}
func getMonthNameFromInt(month: Int) -> String {
switch month {
case 1:
return "Jan"
case 2:
return "Feb"
case 3:
return "Mar"
case 4:
return "Apr"
case 5:
return "May"
case 6:
return "Jun"
case 7:
return "Jul"
case 8:
return "Aug"
case 9:
return "Sept"
case 10:
return "Oct"
case 11:
return "Nov"
case 12:
return "Dec"
default:
return ""
}
}
How to call?
setTimestamp(epochTime: time) and you'll get the desired output as a string.
Convert timestamp into Date object.
If timestamp object is invalid then return current date.
class func toDate(_ timestamp: Any?) -> Date? {
if let any = timestamp {
if let str = any as? NSString {
return Date(timeIntervalSince1970: str.doubleValue)
} else if let str = any as? NSNumber {
return Date(timeIntervalSince1970: str.doubleValue)
}
}
return nil
}
Swift:
extension Double {
func getDateStringFromUnixTime(dateStyle: DateFormatter.Style, timeStyle: DateFormatter.Style) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = dateStyle
dateFormatter.timeStyle = timeStyle
return dateFormatter.string(from: Date(timeIntervalSince1970: self))
}
}
Anyway #Nate Cook's answer is accepted but I would like to improve it with better date format.
with Swift 2.2, I can get desired formatted date
//TimeStamp
let timeInterval = 1415639000.67457
print("time interval is \(timeInterval)")
//Convert to Date
let date = NSDate(timeIntervalSince1970: timeInterval)
//Date formatting
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd, MMMM yyyy HH:mm:a"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let dateString = dateFormatter.stringFromDate(date)
print("formatted date is = \(dateString)")
the result is
time interval is 1415639000.67457
formatted date is = 10, November 2014 17:03:PM
If you are maximizing the Codable protocol for parsing your JSON data. You could simply make the data type of dt as Date and do:
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
For me: Converting timestamps coming from API to a valid date :
`let date = NSDate.init(fromUnixTimestampNumber: timesTamp /* i.e 1547398524000 */) as Date?`
By using this code you will be able to convert timeStamp to Time and Date
let timeStamp = Date().timeIntervalSince1970
let date = NSDate(timeIntervalSince1970: timeStamp)
let dayTimePeriodFormatter = DateFormatter()
dayTimePeriodFormatter.dateFormat = "dd MMMM,YYYY.hh:mm a"
let dateTimeString = dayTimePeriodFormatter.string(from: date as Date)
let dateTime = dateTimeString.split(separator: ".")
print( "Date = \(dateTime[0])")
print( "Time = \(dateTime[1])")
Output:
Date = 19 January,2022
Time = 10:46 AM

Resources