I can get it to work fine using just Strings but if I try to use Doubles or NSDates then I get an error:
"Cannot assign value of type "NSDate?" to type "String?"
"Cannot assign value of type "Double?" to type "String?"
#IBAction func save(_ sender: Any) {
if item != nil {
item?.startdate = startDate.text
item?.pickup = pickup.text
item?.miles = miles.text
item?.company = company.text
item?.destination = destination.text
item?.enddate = endDate.text
} else {
let entitydescription = NSEntityDescription.entity(forEntityName: "Entity", in: pc)
let item = Entity(entity: entitydescription!, insertInto: pc)
item.startdate = startDate.text
item.pickup = pickup.text
item.miles = miles.text
item.company = company.text
item.destination = destination.text
item.enddate = endDate.text
}
do {
try pc.save()
} catch {
print(error)
return
}
navigationController!.popViewController(animated: true)
}
Here is what type each field is:
#NSManaged public var startdate: NSDate?
#NSManaged public var pickup: String?
#NSManaged public var miles: Double
#NSManaged public var company: String?
#NSManaged public var destination: String?
#NSManaged public var enddate: NSDate?
You need to convert miles.text, startdate.text and enddate.text to Double, NSDate and NSDate, respectively.
For startdate.text / enddate.text:
I'm not sure how what limit you have set for these values when the item is saved, but you should use a default value just incase the conversion fails. For this example, assume the dates are formatted "5/15/17" which takes the format M/d/y
let defaultDate = NSDate() //current date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "M/d/y"
if let startDateText = startdate.text, let startDate = dateFormatter.string(from: startDateText) as? NSDate {
item?.startdate = startDate
} else {
item?.startdate = defaultDate
}
if let endDateText = startdate.text, let endDate = dateFormatter.string(from: endDateText) as? NSDate {
item?.startdate = endDate
} else {
item?.startdate = defaultDate
}
For miles.text:
Same idea, use a default value incase the conversion failed based on what the text will be for item.miles
if let milesText = miles.text {
item?.miles = Double(miles.text) ?? 0.0 //default is 0.0
} else {
item?.miles = 0.0
}
or an easy one-liner—
item?.miles = Double(miles.text ?? "0.0")
if there's a specific default value you have in mind, just declare it before you assign the item's property,
let defaultMilesStr = "0.432"
item?.miles = Double(miles.text ?? defaultMiles)
Also, just a tip, it's good practice to not leave optionals wrapped when assigning values. So even though there was check to make sure item != nil, it's overall better to safely unwrap item with a "guard" or "if-let". Since you are creating a new item if one doesn't exist, id go with if-let in this case:
if let item = item {
// assign values to item's prop's
// item.startdate = .....
} else if let entityDescription = NSEntityDescription.entity(forEntityName: "Entity", in: pc), let item = Entity(entity: entityDescription, insertInto: pc) {
// assign values to item's prop's
// item.startdate = .....
}
//further execution
Convert your date string to NSdate then you are able to save that
Try this code i have provide my date string you mat change with your format
let dateString = "Thu, 22 Oct 2015 07:45:17 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy hh:mm:ss +zzzz"
dateFormatter.locale = Locale.init(identifier: "en_GB")
let dateObj = dateFormatter.date(from: dateString)
dateFormatter.dateFormat = "MM-dd-yyyy"
Try this :
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = /* date_format_you_want_in_string from
* http://userguide.icu-project.org/formatparse/datetime
*/
let date = dateFormatter.date(from: /* your_date_string */)
and set it as :
item?.date = date
For miles you can use :
if let dMiles = Double(miles.text!) {
item?.miles.text = dMiles
} else {
print("Not a valid Double: \(textField.text!)")
}
Hope it Helps!!
Related
I have a list of arrays that contains date object along with time, I have a record like in the this date format yyyy-MM-dd'T'HH:mm:ssZ I want to filter my array with ascending order and I also want to store unique values as in dates.
I am having record like 2021-04-01T11:00:00-04:00, 2021-04-01T12:00:00-04:00, 2021-04-02T09:00:00-04:00, 2021-04-02T10:00:00-04:00 and what I want 2021-04-01T11:00:00-04:00, 2021-04-02T09:00:00-04:00
Means before time value but only once. I have used this code but not working
let totalPods = [Items]
self.totalPods.sort { (firstItem, secondItem) -> Bool in
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // "2021-04-01T11:00:00-04:00"
let firstDate = dateFormatter.date(from: firstItem.startDateString)
let secondDate = dateFormatter.date(from: secondItem.startDateString)
if let safeSecondDate = secondDate {
return firstDate?.compare(safeSecondDate) == .orderedAscending
}
return false
}
struct Items: Hashable {
let startDateString: String
}
let totalPods: [Items] = [Items(startDateString: "2021-04-01T11:00:00-04:00"),
Items(startDateString: "2021-04-01T12:00:00-04:00"),
Items(startDateString: "2021-04-02T09:00:00-04:00"),
Items(startDateString: "2021-04-02T10:00:00-04:00"),
Items(startDateString: "2021-04-01T11:00:00-04:00"),
Items(startDateString: "2021-04-01T11:00:00-04:00")]
// Store unique values
let uniqs = Array(Set(totalPods))
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
// filter by ASC
let sorted = uniqs.sorted { (item1, item2) in
dateFormatter.date(from: item1.startDateString)!.compare(dateFormatter.date(from: item2.startDateString)!) == .orderedAscending
}
// You can extend your model
extension Items {
var date: Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return dateFormatter.date(from: startDateString)!
}
}
// And sort like this
let sorted = uniqs.sorted { (item1, item2) in
item1.date.compare(item2.date) == .orderedAscending
}
How do I format this date so that it is readable. I want it to show for example: "January 7th, 2018 7:30am". I tried to look at other answers but wasn't sure where to add the extension.
let date = Date(timeIntervalSince1970: request.timestamp / 1000)
dateCell.textLabel?.text = date.description
class Request {
var key:String
var sender:String
var recipient:String
var name:String
var location:String
var when:String
var whereStr:String
var message:String
var timestamp:Double
var status:String
init(dict: [String: Any]) {
self.key = dict["key"] as? String ?? ""
self.sender = dict["sender"] as? String ?? ""
self.recipient = dict["recipient"] as? String ?? ""
self.name = dict["name"] as? String ?? ""
self.location = dict["location"] as? String ?? ""
self.when = dict["when"] as? String ?? ""
self.whereStr = dict["where"] as? String ?? ""
self.message = dict["message"] as? String ?? ""
self.timestamp = dict["timestamp"] as? Double ?? 0.0
self.status = dict["status"] as? String ?? ""
}
Try This
func getCurrentDateTimeFromTimeStamp(timeStapm:String)->String{
let date = NSDate(timeIntervalSince1970:Double(timeStapm)!/1000)
let formatter = DateFormatter()
formatter.dateFormat = "MMMM d, yyyy HH:mm a"
return formatter.string(from: date as Date)
}
pass timestamp and get as date in string format as per your requirement just pass dateFormat.
use like this
dateCell.textLabel?.text = self.getCurrentDateTimeFromTimeStamp(timeStapm:"pass your timestamp")
You should use DateFormatter:
let formatter = DateFormatter()
formatter.format = "MMMM d, yyyy HH:mm a"
let dateString = formatter.string(from: date)
Use a dateFormatter object to style the date however you want
let format = DateFormatter()
format.format = "MM/dd/yyyy"
//get your date in string like this
let dateInString = format.string(from: date)
// this will give you "10/02/2018"
You can visit date format examples to see different format and how to get them.
You can add extension anywhere in the app and one (same name) extension for comlpete app. look below
import UIKit
class ViewControllerHellBoy: UIViewController
{
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
dateCell.textLabel?.text = self.userFriendlyFullDate()
}
}
extension Date: Dateable {
var formatter: DateFormatter { return DateFormatter() }
/** Return a user friendly hour */
func userFriendlyFullDate() -> String {
// Customize a date formatter
formatter.dateFormat = ""MMMM d, yyyy HH:mm a"" //Use format you want to
formatter.timeZone = TimeZone(abbreviation: "UTC") . // Time zone you wishes to provide
return formatter.string(from: self)
}
That is how you can use extensions. You can also create separate class and keep all extensions there.
I am try to compare two date-
dateArrayForCompare, is the date which i get from NSDate and, dateArrayServer, is the date which i get from json response.
var dateArrayServer = NSMutableArray()
var dateArrayCalendar = NSMutableArray()
var dateArrayForCompare = NSMutableArray()
let dateHomework:NSArray = allAsign.valueForKey("date") as! NSArray
let homeWork = allAsign.valueForKey("assignmenttype") as! NSArray
for date in dateHomework{
self.dateArrayServer.addObject(date as! String)
}
let sys_date = NSDate()
print("System Date: \(sys_date)")
let df = NSDateFormatter()
df.dateFormat = "dd-MM-yyyy"
let currentDate = df.stringFromDate(sys_date)
print("String Date: \(currentDate)")
for dt in 0...self.dateArrayServer.count-1
{
if(self.dateArrayServer.objectAtIndex(dt) .isEqualToString("\(self.dateArrayForCompare)"))
{
print("Assignment on date: \(self.dateArrayServer.objectAtIndex(dt)) are:\n\(allAsign.objectAtIndex(dt))")
}else
{
print("\(self.dateArrayServer.objectAtIndex(dt)) doesn't match with \(self.dateArrayForCompare) ")
}
}
But get this result-
Something like this (swift 2.2)
for dt in 0 ... dateArrayServer.count-1
{
let date1 = dateArrayServer.objectAtIndex(dt) as! String
for value in dateArrayForCompare.enumerate() {
if date1 == value.element as! String {
print(date1)
}
}
}
I have a CoreData attributes that 2 (value, date). When I click on a UIButton, it added an entry corresponding to the value of the UIButton.
I will wish to limit the addition of entry to a daily. Basically, I will wish to check the current date and the date of the last entry. If it's value are identical, this is not added.
My Function
func data(sender: UIButton) {
// Date Format
let date = NSDate()
let formatter = NSDateFormatter()
formatter.dateFormat = "YYYY/MM/dd"
let dateFormat = formatter.stringFromDate(date)
// Load Entity
let AppDel : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let theContext : NSManagedObjectContext = AppDel.managedObjectContext
let theEnt = NSEntityDescription.entityForName("Mood", inManagedObjectContext: theContext)
// Create Item
let newItem = Mood(entity: theEnt!, insertIntoManagedObjectContext: theContext)
newItem.mood = String(sender.tag)
newItem.date = dateFormat
// Save Item
do {
try theContext.save()
} catch _ {
}
}
Thank you in advance for your response.
If you fetch the Mood objects, sorted by date in descending order, the first item returned will be the last entry. You can set the fetchLimit to 1 to avoid loading more objects than are necessary. You can then test to see whether the date attribute matches, and handle accordingly:
func data(sender: UIButton) {
// Date Format
let date = NSDate()
let formatter = NSDateFormatter()
formatter.dateFormat = "YYYY/MM/dd"
let dateFormat = formatter.stringFromDate(date)
// Get context and entity details
let AppDel : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let theContext : NSManagedObjectContext = AppDel.managedObjectContext
let theEnt = NSEntityDescription.entityForName("Mood", inManagedObjectContext: theContext)
// Fetch the latest entry
let fetch = NSFetchRequest()
fetch.entity = theEnt!
let sort = NSSortDescriptor(key: "date", ascending:false)
fetch.sortDescriptors = [sort]
fetch.fetchLimit = 1
let results = try! theContext.executeFetchRequest(fetch) as! [Mood]
// NB should do proper try/catch error checking
// Check for existing entry
if (results.count > 0) {
// Check whether date matches
if (results[0].date != dateFormat) {
let newItem = Mood(entity: theEnt!, insertIntoManagedObjectContext: theContext)
newItem.mood = String(sender.tag)
newItem.date = dateFormat
}
} else { // No entries yet, I assume you want to add one...
let newItem = Mood(entity: theEnt!, insertIntoManagedObjectContext: theContext)
newItem.mood = String(sender.tag)
newItem.date = dateFormat
}
// Save Item
do {
try theContext.save()
} catch _ {
}
}
Note that (given your code newItem.date = dateFormat) I am assuming the date attribute is a string which you set using the same format ("YYYY/MM/dd"). This strips out the time information and so avoids the need for the date comparisons, but also has the advantage that a string sort is equivalent to a date sort (perhaps you chose that format for that reason). If date is in fact a Date attribute, the sort will still work but you will need to use a date comparison.
I use an NSDate extension for this.
extension NSDate {
class func areDatesSameDay(dateOne:NSDate,dateTwo:NSDate) -> Bool {
let calender = NSCalendar.currentCalendar()
let flags: NSCalendarUnit = [.Day, .Month, .Year]
let compOne: NSDateComponents = calender.components(flags, fromDate: dateOne)
let compTwo: NSDateComponents = calender.components(flags, fromDate: dateTwo);
return (compOne.day == compTwo.day && compOne.month == compTwo.month && compOne.year == compTwo.year);
}
}
Usage is like this.
if NSDate.areDatesSameDay(dateOne, dateTwo: dateTwo) {
// Dates are same day
} else {
// Dates are not the same day
}
#Tom Harrington Has just pointed out that you can use the NSCalendar methods to do this more simply
let calender = NSCalendar.currentCalendar()
if calender.isDate(dateOne, inSameDayAsDate: dateTwo) {
// Dates are same day
}
So we can make my lovely extension even simpler...
extension NSDate {
func isSameDayAs(date:NSDate) -> Bool {
let calender = NSCalendar.currentCalendar()
return calender.isDate(self, inSameDayAsDate: date)
}
}
Then use it like this.
if dateOne.isSameDayAs(dateTwo) {
// Dates are same day
} else {
// Dates are not the same day
}
And thats Numberwang!
There's an exception when I run it.
self.year = value as! NSString
Exception:
Could not cast value of type '__NSDate' (0x1051bd6a0) to 'NSString' (0x10564d8e0).
What am I missing ?
var datePicker = ActionSheetDatePicker(title: "Date:",datePickerMode: UIDatePickerMode.Date, selectedDate: NSDate(),doneBlock: {
picker, value, index in
self.year = value as! NSString
println("year = \(year)")
println("value = \(value)")
return
}, cancelBlock: { ActionStringCancelBlock in return }, origin: sender.superview!.superview)
I think you have to convert date to string via your selected value
let formatter: DateFormatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd-HH-mm-ss"
let dateStr: String = formatter.string(from: value as! Date)
You can use any other format like : "yyyy" or "HH:mm:ss" etc.
and set it to your year variable
self.year = dateStr