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

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")

Related

Getting Hour value from time string in Swift

I am trying to get an Int value for Hour from a string.
let time = 13:24
func getNtfHour() -> Date{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH"
let result = dateFormatter.date(from: time)!
return result //2000-01-01 08:24:00 +0000
}
As you can see my current code return a whole date and the time does not match with the string. How do I fix it?
edit: I managed to to this by using date components
let time = 13:24
func getNtfHour() -> Int{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
let result = dateFormatter.date(from: time)!
let calendar = Calendar.current.component(.hour, from: result)
return calendar //13
}
As a time string is actually not related to a Dateformatter an easier way is to parse the string directly.
If the hour has always two digits
let time = "13:24"
let hour = Int(time.prefix(2))
or otherwise
let time = "13:24"
if let range = time.range(of: "^\\d+", options: .regularExpression) {
let hour = Int(time[range])
}

How to store date in userdefaults?

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)

How to get Int from DateFormatter() in Swift3

I want to remove some data from my UITableView when the data is passed over 24 hours. I saved date as String. I want to check the date but because it is String, how am I able to turn that data into Int value in order to check how many hours have passed since the data is last entered? Is there any good code for that to happen? This date data is stored in Firebase.
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.timeStyle = .medium
formatter.dateStyle = .long
let date = formatter.string(from: currentDateTime)
You need:
Your date
Add 24 hours to that date
Compare that new date with "now"
I am assuming you have some date already:
let myDate: Date = ...
Let's add 24 hours:
let endDate: Date = Calendar.current.date(byAdding: .hour, value: 24, to: myDate, wrappingComponents: true)!
Did 24 hours already passed since my date?
let now = Date()
let expired = (endDate < now)
I am not sure why would you even use a date formatter for this task.
Try this:
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.dateFormat = "hh"
let date = formatter.string(from: currentDateTime)
print(date)// Time in string
print(Int(date)!) // Time in Int

Swift displaying the time or date based on timestamp

I have an API that returns data including a timestamp for that record.
In swift I have the timestamp element loaded and converted into a double and can then convert that into time. I want to be able to return the time if the date of the record is today and return the date if the record is not today.
See below:
let unixTimeString:Double = Double(rowData["Timestamp"] as! String)!
let date = NSDate(timeIntervalSince1970: unixTimeString) // This is on EST time and has not yet been localised.
var dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = .ShortStyle
dateFormatter.doesRelativeDateFormatting = true
// If the date is today then just display the time, if the date is not today display the date and change the text color to grey.
var stringTimestampResponse = dateFormatter.stringFromDate(date)
cell.timestampLabel.text = String(stringTimestampResponse)
Do I use NSCalendar to see if 'date' is today and then do something?
How do you then localise the time so that its correct for the user rather than server time?
There is a handy function on NSCalendar that tells you whether an NSDate is in today or not (requires at least iOS 8) isDateInToday()
To see it working, put this into a playground:
// Create a couple of unix dates.
let timeIntervalToday: NSTimeInterval = NSDate().timeIntervalSince1970
let timeIntervalLastYear: NSTimeInterval = 1438435830
// This is just to show what the dates are.
let now = NSDate(timeIntervalSince1970: timeIntervalToday)
let then = NSDate(timeIntervalSince1970: timeIntervalLastYear)
// This is the function to show a formatted date from the timestamp
func displayTimestamp(ts: Double) -> String {
let date = NSDate(timeIntervalSince1970: ts)
let formatter = NSDateFormatter()
formatter.timeZone = NSTimeZone.systemTimeZone()
if NSCalendar.currentCalendar().isDateInToday(date) {
formatter.dateStyle = .NoStyle
formatter.timeStyle = .ShortStyle
} else {
formatter.dateStyle = .ShortStyle
formatter.timeStyle = .NoStyle
}
return formatter.stringFromDate(date)
}
// This should just show the time.
displayTimestamp(timeIntervalToday)
// This should just show the date.
displayTimestamp(timeIntervalLastYear)
Or, if you just want to see what it looks like without running it yourself:
Abizern's answer in Swift 3:
import UIKit
let timeIntervalToday: TimeInterval = Date().timeIntervalSince1970
let timeIntervalLastYear: TimeInterval = 1438435830
// This is just to show what the dates are.
let now = Date(timeIntervalSince1970: timeIntervalToday)
let then = Date(timeIntervalSince1970: timeIntervalLastYear)
// This is the function to show a formatted date from the timestamp
func displayTimestamp(ts: Double) -> String {
let date = Date(timeIntervalSince1970: ts)
let formatter = DateFormatter()
//formatter.timeZone = NSTimeZone.system
if Calendar.current.isDateInToday(date) {
formatter.dateStyle = .none
formatter.timeStyle = .short
} else {
formatter.dateStyle = .short
formatter.timeStyle = .none
}
return formatter.string(from: date)
}
// This should just show the time.
displayTimestamp(ts: timeIntervalToday)
// This should just show the date.
displayTimestamp(ts: timeIntervalLastYear)

Convert a mysql date to NSDate then check how many days between

I'm having problems with NSDate in Swift.
I JSON a date formatted in Y-m-d from my database. This is stored as a string called survey_date
I then convert the string to a NSDate using dateFormatter
I want to work out the amount of days between the survey_date and NOW
Error in my script is endDate is ambiguous expression without more context.
Here is my script:
var survey_date = prefs.valueForKey("SURVEY_DATE") as! String
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
var date = dateFormatter.dateFromString(survey_date) as NSDate!
let outputDate = dateFormatter.stringFromDate(date)
println(outputDate)
let start = outputDate
let end = NSDate()
let dateFormatter2 = NSDateFormatter()
dateFormatter2.dateFormat = "yyyy-MM-dd"
let startDate:NSDate = dateFormatter2.dateFromString(start)!
let endDate:NSDate = dateFormatter2.dateFromString(end)!
let cal = NSCalendar.currentCalendar()
let unit:NSCalendarUnit = .CalendarUnitDay
let components = cal.components(unit, fromDate: startDate, toDate: endDate, options: nil)
println(components)
Secondly, I also want to be able to convert the date when possible to a different format - for example d m, Y. This is pretty simple to do in PHP but I can't find a way of doing it in Swift? I don't want to have to send extra data through JSON (i.e. create a $formatted_date) but it looks like this is my only option (which I know is messy and I will get told off for!)
You get a compiler error in
let endDate:NSDate = dateFormatter2.dateFromString(end)!
because dateFromString() is called with a date instead of a string,
which makes no sense.
Your computation is a bit too complicated, you can shorten it to
let survey_date = "2015-05-01"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let startDate = dateFormatter.dateFromString(survey_date) {
let endDate = NSDate()
let cal = NSCalendar.currentCalendar()
let components = cal.components(.CalendarUnitDay, fromDate: startDate, toDate: endDate, options: nil)
let days = components.day
println(days)
} else {
println("invalid input")
}
If you want to convert the date into a different format then
(as Leo already said in a comment), use stringFromDate() with
a second date formatter, e.g.
let dateFormatter2 = NSDateFormatter()
dateFormatter2.dateFormat = "d MM, Y"
let formattedStartDate = dateFormatter2.stringFromDate(startDate)
println(formattedStartDate)
Here's something you may find handy. I was working on an app that did a lot of date calculations, and therefore was making lots of calls to NSCalendar's components(_:fromDate:toDate:options:) method. This doesn't feel terribly Swift-like, so I overloaded the - operator to do date subtractions:
func -(lhs: NSDate, rhs: NSDate) -> NSDateComponents
{
let components: NSCalendarUnit =
.CalendarUnitSecond |
.CalendarUnitMinute |
.CalendarUnitHour |
.CalendarUnitDay
return NSCalendar.currentCalendar().components(components,
fromDate: rhs,
toDate: lhs,
options: nil)
}
This lets you find the difference between any two dates/times by simple subtraction. Here's a quick example:
// MySQL date formatter
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// Let's create a couple of dates that we know are one day apart
let christmas2015 = dateFormatter.dateFromString("2015-12-25")!
let christmasEve2015 = dateFormatter.dateFromString("2015-12-24")!
let difference = christmas2015 - christmasEve2015
let daysBetween = difference.day // this value is 1