How to store date in userdefaults? - swift

I'd like to record the history of her entry into the textfield. I intend to register this with UserDefaults. But when I try to save it with UserDefaults, "cannot assign value of type 'nsdate'?'to type 'String' " Error. I don't think it's accepting textfield data because it's string. And how can I keep history in memory?
formatteddate and formatteddate2 give this error. The date output is as follows : 20/04/2019 20:23
let token = try? keychain.getString("chipnumbernew")
chip1InfoString = token
var time = NSDate()
var formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy HH:mm"
var formatteddate = formatter.string(from: time as Date)
var formatteddate2 = formatter.string(from: time as Date)
timertextNew.text = formatteddate
timertext2New.text = formatteddate2
let RetrivedDate = UserDefaults.standard.object(forKey: "timertext") as? NSDate
formatteddate = RetrivedDate
let RetrivedDate2 = UserDefaults.standard.object(forKey: "timertext2") as? NSDate
formatteddate2 = RetrivedDate2

If you only want to display the date value you can convert and store it as string otherwise you convert/format it after you have read it, either way you should make sure you use the same type when saving and reading
//save as Date
UserDefaults.standard.set(Date(), forKey: key)
//read
let date = UserDefaults.standard.object(forKey: key) as! Date
let df = DateFormatter()
df.dateFormat = "dd/MM/yyyy HH:mm"
print(df.string(from: date))
// save as String
let df = DateFormatter()
df.dateFormat = "dd/MM/yyyy HH:mm"
let str = df.string(from: Date())
UserDefaults.standard.setValue(str, forKey: key)
// read
if let strOut = UserDefaults.standard.string(forKey: key) {
print(strOut)
}

The following saves a Date object as a Double (a.k.a. TimeInterval). This avoids any date formatting. Formatting can lose precision, and is unnecessary since the string is not intended for users to read.
// save
UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: key)
// read
let date = Date(timeIntervalSince1970: UserDefaults.standard.double(forKey: key))

you can always create an extension for saving and retrieving the date in userdefault. here the example code:
import Foundation
extension UserDefaults {
func set(date: Date?, forKey key: String){
self.set(date, forKey: key)
}
func date(forKey key: String) -> Date? {
return self.value(forKey: key) as? Date
}
}
let userDefault = UserDefaults.standard
userDefault.set(date: Date(), forKey: "timertext")
print(userDefault.date(forKey: "timertext") ?? "")

Your problem is that you are retrieving NSDate from the user default storage and then trying to assign them to a String (formatteddate).
Try this;
formatteddate = formatter.string(from: RetrivedDate as Date)

Related

Swift string date to date

I read a date from UserDefaults.standard as string in the following format:
"2020-11-06T05:20:20+0100"
I try to convert this string to a date using the following code
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "de_DE")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let dateString: String! = UserDefaults.standard.string(forKey: "timeShared")
let date = dateFormatter.date(from: dateString)
However, the result is always nil. Using let date = dateFormatter.date(from: dateString)! explicitly causes a fatal error.
Any ideas what to do?
Changing the former code to
dateFormatter.dateFormat = "\"yyyy-MM-dd'T'HH:mm:ssZ\""
returns a neatly formatted date subsequently. The error was that the date read from UserDefaults included "".
May be UserDefaults.standard.string(forKey: "timeShared") have no value or the value is not in string format and you are doing force unwrapping in let dateString: String! = UserDefaults.standard.string(forKey: "timeShared") here that making the fatal error.
Better add a conditional if, then use the dateString.
Refer the below code.
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "de_DE")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
if let dateString: String = UserDefaults.standard.string(forKey: "timeShared") {
let date = dateFormatter.date(from: dateString)
print(date)
} else {
print("Data in UserDefaults: \(UserDefaults.standard.string(forKey: "timeShared"))")
}

Converting timestamp from Firebase and adding to array

I'm trying to read a timeStamp from Firebase and append it to an array.
I have made some progress:
var orderDateHistoryArray = [String:Int]()
func getOrderDates() {
let uid = Auth.auth().currentUser!.uid
let orderDateHistoryRef = Database.database().reference().child("users/\(uid)/Orders/")
orderDateHistoryRef.observeSingleEvent(of: .value, with: { (snapshot) in
// Get dates
let value = snapshot.value as? NSDictionary
if let orderDate = value?["Date"] as? [String:Int] {
self.orderDateHistoryArray += Array(orderDate.values)//This does not conform
print(orderDate)
}
self.tableView.reloadData()
// ...
}) { (error) in
print(error.localizedDescription)
}
}
The print(orderDate)statement prints:
["-LQYspEghK3KE27MlFNE": 1541421618601,
"-LQsYbhf-vl-NnRLTHhK": 1541768379422,
"-LQYDWAKlzTrlTtO1Qiz": 1541410526186,
"-LQsILjpNqKwLl9XBcQm": 1541764115618]
This is childByAutoID : timeInMilliseconds
So, I want to read out the timeInMilliseconds, convert it to a readable timestampand append it to the orderDateHistoryArray
Those are timestamps. Parse it as a Date object then use .toLocaleDateString to get date.
alert( new Date(1541421618601).toLocaleDateString("en-US") );
In order to transform your timestamp you must, first remove milliseconds on each the values returned by the dictionary.
self.orderDateHistoryArray += Array(orderDate.values).map { Date(timeIntervalSince1970: TimeInterval($0/1000)) }
In order to get it in a "human way", you need to have a DateFormatter. It's on this object where you define how it's presented.
extension Date {
func format(_ dateFormat: String = "dd/MMMM")
let formatter = DateFormatter()
formatter.timeZone = TimeZone.current
formatter.dateFormat = "MMMM dd"
return formatter.string(from: self)
}
}
and on a Date element you can just call it by date.format() or by passing a string date.format("yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX")

Error in DataPicker Format

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm "
let selectedDate = dateFormatter.string(from: sender.date)
UserDefaults.standard.set(selectedDate, forKey: "date")
print(selectedDate)
\\method to reload the selected time inside the viewdidLoad func
let selectedDate = UserDefaults.standard.object(forKey: "date")
example.setDate(selectedDate as! Date ?? Date(), animated: false)
But when I run the application it returns this error
Could not cast value of type '__NSCFString' (0x108e8b4f0) to 'NSDate' (0x108e8c0d0).
I converted to HH: mm because I want to record only the time in this format, but I do not know how I'm going to handle it
You should be storing the Date object itself in UserDefaults and not its String representation. In most use cases, it makes more sense to store a Date object, since Date objects represent an absolute point in time and hence you can use them for date comparison or to convert them to local times.
Moreover, it looks like that the setDate function actually expects a Date object and not a String, hence it doesn't make sense to generate a String representation of a Date and then store that in UserDefaults.
//Save the Date object
UserDefaults.standard.set(sender.date, forKey: "date")
//Retrieve the Date object, if it cannot be retrieved, use the current Date
if let selectedDate = UserDefaults.standard.object(forKey: "date") as? Date {
example.setDate(selectedDate, animated: false)
} else {
example.setDate(Date(), animated: false)
}
Andre you save String value in UserDefaults and try to set NSDate from String. If you concern with the time only then my advice to save the date as it is in UserDefaults and get the time as formatted as per as your requirement.
Here are the following steps for saving and retrieving Time :
For saving:
func datePickerChanged(_ sender: UIDatePicker){
UserDefaults.standard.set(sender.date, forKey: "date")
}
For Retrieving:
func getTime(){
let date = UserDefaults.standard.object(forKey: "date") as! Date
let dateFormatter = DateFormatter()
dateFormatter.locale = NSLocale.current
dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone! //Set your own time zone here.
dateFormatter.dateFormat = "HH:mm"
print(dateFormatter.string(from: date as Date))
example.setDate(date, animated: false)
}
Hope it will help you and save your time.

Swift - How to store multiple date in default and retrieve it?

This is my code. I want to save todayString and nextString in user default so that I can display the stored date (update every Tuesday) in label when it's not Tuesday.
let today = NSDate()
let nextTue = Calendar.current.date(byAdding: .day, value: 6, to: today as Date)
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
let todayString = formatter.string(from: today as Date)
let nextString = formatter.string(from: nextTue!)
formatter.dateFormat = "dd-MMM-yyyy"
let calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)
let components = calendar!.components([.weekday], from: today as Date)
if components.weekday == 3 {
print("Hello Tuesday")
thisWeekDate.text! = "\(todayString) - \(nextString)"
} else {
print("It's not Tuesday")
}
NSUserDefaults saves data between runs of apps using the device storage.
The easiest way in your case would be to save two different date objects, or you can create a dictionary containing both date objects and save it instead.
Store
UserDefaults.standard.set(todayString, forKey: "todayStringKey")
Retrieve
let RetrivedDate = UserDefaults.standard.object(forKey: "todayStringKey") as? NSDate
Remove - in case you want to delete it completely from storage
UserDefaults.standard.removeObject(forKey: "todayStringKey")

How to convert an array of date strings to an array of date objects, Swift

Looked at similar SO questions and found that there are no answers in Swift, there are plenty of answers exclusively for date formatting but not in combination with iteration.
I have an array of date strings like the below:
let dateStrings = ["2016-12-22T08:00:00-08:00", "2016-12-22T08:15:00-08:00", "2016-12-22T08:30:00-08:00"]
I would like to convert them to an array of local dateObjects like the below
var dateObjects = [2016-12-22 21:30:00 +0530, 2016-12-22 21:45:00 +0530, 2016-12-22 22:00:00 +0530]
I've tried iterating through the array of date strings but I get this error :
"fatal error: unexpectedly found nil while unwrapping an Optional value"
So I tried with optional binding without success. Please advice where I could be going wrong.
var dateObjects = [Date]()
let dateFormatter = DateFormatter()
for date in dateStrings{
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let dateObject = dateFormatter.date(from: date)
self.dateObjects.append(dateObject!) // ERROR LINE
}
When I try with optional binding its going through else statement printing "Unable to convert to date object"
for date in dateStrings{
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
if let dateObject = dateFormatter.date(from: date){
self.dateObjects.append(dateObject!) // ERROR LINE
}
else{
print("Unable to convert to date object")
}
}
In second case you are force wrapping non-optional value there is no need of that and you are writing self with dateObjects var that is not declare as a instance property, also you can simply use flatMap to reduce your code and create array of Date from array of String.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let dateObjects = dateStrings.flatMap { dateFormatter.date(from: $0) }
Try this: date object is local variable so remove self. if you want use self then make it global
let dateStrings = ["2016-12-22T08:00:00-08:00", "2016-12-22T08:15:00-08:00", "2016-12-22T08:30:00-08:00"]
var dateObjects = [Date]()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
for date in dateStrings{
let dateObject = dateFormatter.date(from: date)
dateObjects.append(dateObject!)
}
print(dateObjects)
Simply remove self from dateObjects.
dateObjects is local variable. So don't use self with dateObjects.
var dateObjects = [Date]()
let dateFormatter = DateFormatter()
for date in dateStrings{
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let dateObject = dateFormatter.date(from: date)
dateObjects.append(dateObject!)
}
What I did was that I mapped over the the array and made each item into a new Date object.
let dateObjects = _.map(dateStrings, (dateString) => new Date(dateString)
It's that easy. In my case, I was trying to compare the dates to another array of dates so after doing new Date(dateString) I converted them back into a ISOString by doing
let dateObjects = _.map(dateStrings, (dateString) => new Date(dateString).toISOString()
Note:
You don't need to use _.map, you could just use .map
Try This..
Swift 3
let dateStrings = ["2016-12-22T08:00:00-08:00", "2016-12-22T08:15:00-08:00", "2016-12-22T08:30:00-08:00"]
func convertDate(str: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxx"
let dateObject = dateFormatter.date(from: str)
return(dateObject!)
}
var stringDates : [Date] = []
for date in dateStrings {
stringDates.append(convertDate(str: dateStrings[0]))
}