I'm currently getting JSON data for a date in this format:
Date = "2016-07-21T18:32:24.347Z"
I need to be able to add an Int, or float that represents minutes (60 min total)
How can I do this?
So there are like a million different ways that you could do this but that is probably not what you are looking for here. The best way to play with these things would be in a playground that way you can see how the changes to your code effect the end result.
So first you need a function that can take a string as a parameter.
func dateFromJSON(dateString: String?) -> NSDate? {}
This Function will take in our string and return us a NSDate
Then we need a date formatter, There are many different ways you can format a date and you can check out the documentation on them here NSDateFormatter Documentation
so here is an example of a formatter "yyyy-MM-dd'T'HH:mm:ss.SSSZZZ" you can see pretty quickly that different parts refer to differnt peices of a date. IE the yyyy is for the year in this case will give us something like 2016. If it were yy we would only get 16.
Initialize the dateFormatter then apply our format.
You should also throw in some checks to make your code safe. So it should look like this.
func dateFromWebJSON(dateString: String?) -> NSDate? {
guard let dateString = dateString else {
return nil
}
let formatter = NSDateFormatter()
let date = ["yyyy-MM-dd'T'HH:mm:ss.SSSZZZ"].flatMap { (dateFormat: String) -> NSDate? in
formatter.dateFormat = dateFormat
return formatter.dateFromString(dateString)
}.first
assert(date != nil, "Failed to convert date")
return date
}
so now we can call
let time = dateFromWebAPIString(date)
print(time) // Jul 21, 2016, 12:32 PM
Now to add time you have to remember that 1 NSTimeInterval is 1 second. So do some basic math
let min = 60
let hr = 60 * min
then we can add as much time as you want
let newTime = time?.dateByAddingTimeInterval(NSTimeInterval(20 * min))
print(newTime) // "Jul 21, 2016, 12:52 PM"
20 min later. Hope this helps 🖖🏽
Related
I need to convert the UTC time to PST
From backed, I get UTC dates like "2021-06-25T07:00:00Z"
I need to show the dates in Hstack from Provided UTC date to the current date.
I write the following code.
Anyone help to me.
func datesRange(from:Date, to:Date)->[Date]{
if from > to {return [Date]()}
var tmpdate = from
var array:[Date] = []
while tmpdate <= to {
array.append(tmpdate)
tmpdate = Calendar.current.date(byAdding: .day,value: 1, to: tmpdate)!
}
return array
}
extension Date{
func convertTimezone(timezone:String)-> Date{
if let targettimeZone = TimeZone(abbreviation: timezone){
let delta = TimeInterval(targettimeZone.secondsFromGMT(for: self) - TimeZone.current.secondsFromGMT(for: self))
return addingTimeInterval(delta)
}else{
return self
}
}
}
I used as follows
func getrangeDays(){
let startday = "2021-06-25T07:00:00Z"
let dateformater = DateFormatter()
dateformater.locale = Locale(identifier: "en_US_POSIX")
dateformater.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
if let date = dateformater.date(from: startday){
let rangedays = datesRange(from:date.convertTimezone(timezone: "PST") , to: Date().convertTimezone(timezone: "PST"))
print(rangedays)
}
}
Your convertTimezone() function does not make sense. It is trying to convert a Date to a different time zone. A Date object does not have a time zone. It is an instant in time, anywhere on the planet. Time zones only make sense when you want to display a Date, or do time zone specific date calculations. (And in that case you want to create a Calendar object and set its time zone to the desired time zone, then use that Calendar for your date calculations.)
Get rid of that function.
Convert your input date string to a Date as you are doing now (although you might want to use an ISO8601DateFormatter rather than a regular date formatter, since those are specifically intended for handling ISO8601 dates.)
Build your date range using your datesRange() function.
Then use a second DateFormatter to display your dates in PST. (Not convert Dates to PST. That doesn't make sense.)
What do we got: Date+time (format yyyy-mm-dd hh:mm a)
What are we looking for: Time difference in minutes
What operation: NewDate - OldDate
So, I wonder how I could accomplish above goal? I would like to format the date and time to US, regardless from which locale the user has. How can I do that?
Then I will save the 'oldTime' into UserDefaults, and use it for later calculation. The goal is to put the user on delay for 5 minutes and the calculations will be performed to determine if user should be on delay or not.
Just make a function that takes two dates and compares them like this.
import UIKit
func minutesBetweenDates(_ oldDate: Date, _ newDate: Date) -> CGFloat {
//get both times sinces refrenced date and divide by 60 to get minutes
let newDateMinutes = newDate.timeIntervalSinceReferenceDate/60
let oldDateMinutes = oldDate.timeIntervalSinceReferenceDate/60
//then return the difference
return CGFloat(newDateMinutes - oldDateMinutes)
}
//Usage:
let myDateFormatter = DateFormatter()
myDateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
//You'll need both dates to compare, you can get them by just storing a Date object when you first start the timer.
//Then when you need to check it, compare it to Date()
let oldDate: Date = myDateFormatter.date(from: String("2019-06-22 11:25"))
func validateRefresh() {
//do the comparison between the old date and the now date like this.
if minutesBetweenDates(oldDate, Date()) > 5 {
//Do whatever
}
}
You can, of course, change the .dateFormat value on the date formatter to be whatever format you'd like. A great website for finding the right format is: https://nsdateformatter.com/.
You say:
I would like to format the date and time to US, regardless from which locale the user has. How can I do that?
Specify a Locale of en_US_POSIX:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd hh:mm a"
formatter.locale = Locale(identifier: "en_US_POSIX")
The locale is not the only question.
There’s also a timezone question. For example, you're driving out of Chicago and go from Central to Eastern timezones; do you really want to consider that one hour has passed?
Do you really want to discard seconds? If you do that, the 59 seconds between going from 8:00:00pm to 8:00:59pm will be considered “zero minutes” but the one second between 8:00:59pm and 8:01:00pm will be considered “one minute”.
Frankly, if I wanted to save a locale and timezone invariant date string, I’d suggest using ISO8601DateFormatter.
Then I will save the 'oldTime' into UserDefaults, and use it for later calculation.
If that’s why you’re using this DateFormatter, I’d suggest saving the Date object directly.
UserDefaults.standard.set(oldTime, forKey: "oldTime")
And to retrieve it:
if let oldTime = UserDefaults.standard.object(forKey: "oldTime") as? Date {
...
}
In terms of calculating the number of minutes between two Date objects
let minutes = Calendar.current
.dateComponents([.minute], from: date1, to: date2)
.minute
If you want the number of seconds, you can also use timeIntervalSince:
let seconds = date2.timeIntervalSince(date1)
And if you wanted to show the amount of elapsed time as a nice localized string:
let intervalFormatter = DateComponentsFormatter()
intervalFormatter.allowedUnits = [.minute, .second]
intervalFormatter.unitsStyle = .full
let string = intervalFormatter.string(from: date1, to: date2)
I'm not convinced that your question is the best way to go about accomplishing your aim, but the code below will work.
let dateFormatterNow = DateFormatter()
dateFormatterNow.dateFormat = "yyyy-MM-dd hh:mm a"
dateFormatterNow.timeZone = TimeZone(abbreviation: "EST")
let oldDateString = "2019-06-23 12:44 p"
let oldDate = dateFormatterNow.date(from: oldDateString)
let newDateString = "2019-06-23 12:54 p"
let newDate = dateFormatterNow.date(from: newDateString)
if let oldDate = oldDate, let newDate = newDate {
let diffInMins = Calendar.current.dateComponents([.minute], from: oldDate, to: newDate).minute
print(diffInMins)
}
This question already has answers here:
Convert string with unknown format (any format) to date
(2 answers)
Closed 5 years ago.
I'm currently downloading fixture lists for a sports app from a third party website that runs the league, so the data I have to work with is restricted.
I'm trying to implement a feature that displays the next upcoming fixture.
My problem is the dates being retrieved look like this:
"Sat 9th Sep 17" and "Sat 24th Mar 18" for example.
I've tried numerous date formats in the DateFormatter that I know of and can't find anything that uses this specific format.
If I try to use the Date from string method in the date formatter with one of the above strings I get a nil value.
I have an array of fixtures, each with their own dates. I need to compare each of these to the current date to figure out which is next in line.
My temporary fix for this was just to loop through the fixtures and as soon as one did not have a result to display that as the next fixture. Obviously this doesn't work when a game may not have been played for whatever reason.
What would be the best way to deal with this?
Basically you would just need to convert the current date to the same format as the date you get from your third party website (or the opposite) so you can compare them easily:
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EE MMM"
let firstPartStringDate = dateFormatter.string(from: currentDate)
dateFormatter.dateFormat = "yy"
let lastPartStringDate = dateFormatter.string(from: currentDate)
let day = Calendar.current.component(.day, from: currentDate)
let formatter = NumberFormatter()
formatter.numberStyle = .ordinal
guard let ordinalDay = formatter.string(for: day) else {
return
}
let finalDateString = firstPartStringDate + " \(ordinalDay) " + lastPartStringDate
print(finalDateString)
And for today's current date you would get the exactly same format as the one you get from the third-party website :
Sun Sep 17th 17
UPDATE: Here is how you could convert the String you get from the third-party website to a Date, and then compare it with the current date. This solves the problem of having the st, nd, rd and th inside the String at first.
// This is the string you get from the website
var webDateString = "Sat 9th Sep 17"
// First, remove the st, nd, rd or th if it exists :
if let stSubrange = webDateString.range(of:"st") {
webDateString.removeSubrange(stSubrange)
} else if let ndSubrange = webDateString.range(of:"nd") {
webDateString.removeSubrange(ndSubrange)
} else if let rdSubrange = webDateString.range(of:"rd") {
webDateString.removeSubrange(rdSubrange)
} else if let thSubrange = webDateString.range(of:"th") {
webDateString.removeSubrange(thSubrange)
}
// Now convert the string to a date :
dateFormatter.dateFormat = "EE MMM dd yy"
guard let formattedDate = dateFormatter.date(from: finalDateString) else {
return
}
// You can now compare formattedDate and the current date easily like so :
let currentDate = Date()
if formattedDate < currentDate {
// Do something interesting here :)
} else {
// Do something else!
}
I am not sure this has been answered before.
I need to know if its possible to handle two different timezones that are not +0000.
What I mean is that my iphone app calls data from the server such creation date and time of certain objects. But the dates and time is in danish time, meaning timezone the date was created in is something like +0100
But the iphone app thinks the initial timezone is +0000 of course, and if I use dateformatter to set the timezone, it adds an hour to the initial datetime which is incorrect.
Is there a sensible way to handle timezones in Swift, or will I have to subtract an hour manually each time I convert from danish time to whatever is on the phone of the user?
Ideally you need to ask the server side to use GMT +00 so that if they will want to work with some other country it will work fine for everyone..
Or, another way is to store time in Timestamp. And it will be automatically GMT +00
And then the system will handle it for you considering user's time zone on the phone.
Hope it helps
You need to ask Web Service developer if dates which are returning, are those in GMT or not? If not, then ask them to store dates in GMT only.
When api returns data, convert your date to your desired format.
I did this in swift 2.2. Created a String extension.
extension String {
func getFormattedDate(currentFormat : String,convertFormat : String) -> String {
let dateStr = self
let dateFormate = NSDateFormatter()
dateFormate.timeZone = NSTimeZone(abbreviation: "GMT")
dateFormate.dateFormat = currentFormat
if let date = dateFormate.dateFromString(dateStr) {
dateFormate.dateFormat = convertFormat
dateFormate.timeZone = NSTimeZone.localTimeZone()
return dateFormate.stringFromDate(date)
}
return ""
}
func getFormattedDateForDefaultTimeZone(currentFormat : String,convertFormat : String) -> String {
let dateStr = self
let dateFormate = NSDateFormatter()
dateFormate.timeZone = NSTimeZone.localTimeZone()
dateFormate.dateFormat = currentFormat
if let date = dateFormate.dateFromString(dateStr) {
dateFormate.dateFormat = convertFormat
dateFormate.timeZone = NSTimeZone.localTimeZone()
return dateFormate.stringFromDate(date)
}
return ""
}
}
Use like below:
let dateStr = btnDate.currentTitle!.getFormattedDate("dd/MMM/yyyy", convertFormat: "dd-MM-yyyy")
I am making a social app that saves its posts in user specific nodes , with that i am also saving the time of post in this format :-
Wednesday, July 20, 2016, 00:14
which i display with the post in the global feed of friends of the user.
Before 24 hours of that post , i want to display time of post on the feed as this :- "5 Hours Ago"
After 24 hours of that post time of post becomes something like this :- "Yesterday"...
After 48 hours of that post time of post becomes something like this :- "On 5 Aug"...
So far i have come up with these two options:-
1.) Change the time of the feed in the database, which i think would be much better option.
2.) Retrieve the time of post , iterate through MULTIPLE if conditions and set the time of post accordingly.
I would be able to implement the second option but i have no clue to how to go forward with option one
Given that my JSON tree is something like this
appname:{
users : {....
.....
user1 : {....
.....
postsCreated : {
post1 : {
..
timeofPost : ""Wednesday, Aug 5, 2016, 00:14""
}
}
}
}
}
I did stumble upon http://momentjs.com/ but thats for Javascript
Also any suggestion on my JSON tree or is it fine the way it is?
You propose:
Change the time of the feed in the database, which i think would be much better option.
No, the date in the database, as well as that which is communicated with web service, should not be a formatted string. The database and the web service should be capturing the raw dates (or, more accurately, RFC3339/ISO8601 format or seconds from some reference date). The formatting of the elapsed time in a string for the UI is the responsibility of the app.
Retrieve the time of post, iterate through MULTIPLE if conditions and set the time of post accordingly.
Yes, that's what you should do.
By the way, if you're going to omit the year, you probably have a fourth permutation which includes year if the date is more than one year in the past, e.g.:
func formattedPostDateString(date: NSDate) -> String {
let now = NSDate()
let elapsed = NSCalendar.currentCalendar().components([.Day, .Year], fromDate: date, toDate: now, options: [])
switch (elapsed.year, elapsed.day) {
case (0, 0):
return "\(elapsedFormatter.stringFromDate(date, toDate: now)!) \(agoDateString)"
case (0, 1):
return yesterdayString
case (0, _):
return "\(onDateString) \(lessThanOneYearFormatter.stringFromDate(date))"
default:
return "\(onDateString) \(moreThanOneYearFormatter.stringFromDate(date))"
}
}
Where
let onDateString = NSLocalizedString("On", comment: "prefix used in 'On 5 Aug'")
let agoDateString = NSLocalizedString("ago", comment: "suffix use in '4 hours ago'")
let yesterdayString = NSLocalizedString("Yesterday", comment: "showing 'date' where it's between 24 and 48 hours ago")
let elapsedFormatter: NSDateComponentsFormatter = {
let formatter = NSDateComponentsFormatter()
formatter.allowedUnits = [.Year, .Month, .Day, .Hour, .Minute, .Second]
formatter.unitsStyle = .Full
formatter.maximumUnitCount = 1
return formatter
}()
let lessThanOneYearFormatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.dateFormat = NSDateFormatter.dateFormatFromTemplate("MMM d", options: 0, locale: nil)
return formatter
}()
let moreThanOneYearFormatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.dateStyle = .MediumStyle
return formatter
}()
The only thing you need to do is to convert the string returned by the web service into NSDate object. To that end, the web service should probably return the post date in ISO 8601/RFC 3339 format (e.g. 2016-08-26T15:01:23Z format).
To create ISO8601/RFC3339 dates in Swift 2:
let isoDateFormatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
return formatter
}()
And then:
let string = isoDateFormatter.stringFromDate(date)
Or
let date = isoDateFormatter.dateFromString(string)
Or in iOS 10+ using Swift 3, you can use the new ISO8601DateFormatter:
let isoDateFormatter = ISO8601DateFormatter()