Swift convert NSTimeInteval to NSDate - ios

I've been following an Objective-C tutorial and the tutor is able to cast an NSTimeInterval object to a NSDate object.
The lesson uses CoreData, and stores the date of a post as an NSTimeInterval, later on we want to retrieve that interval and set it as a formatted date string to present as a section title in a UITableVIewController.
class DiaryEntry: NSManagedObject {
#NSManaged var date: NSTimeInterval
#NSManaged var body: String
#NSManaged var imageData: NSData
#NSManaged var mood: Int16
#NSManaged var location: String
func sectionName() -> String {
let date = NSDate().dateByAddingTimeInterval(self.date)
let f = NSDateFormatter()
f.dateFormat = "MMM yyy"
return f.stringFromDate(date)
}
}
Mainly concerned with the line:
let date:NSDate = NSDate().dateByAddingTimeInterval(self.date)
Which right now is actually adding the set date onto the current date, and this is not the behaviour I want.
How do I cast the self.date variable to an NSDate object in SWIFT?

There is a initializer of NSDate that takes NSTimeInterval:
init(timeIntervalSinceReferenceDate ti: NSTimeInterval)
So just do:
var date = NSDate(timeIntervalSinceReferenceDate: 123)

This code is really confused.
A time interval is not a date. A date is a point in time. A time interval is the difference in seconds between two points in time. Whenever you have a time interval, you have the question "it is the number of seconds between what two dates? You correctly realise that adding a time interval stored in a database to NSDate () is unlikely to give a useful result, because the same call executed 10 seconds later will give a different date.
The date of a post should most likely be stored as an NSDate object. Core Data handles NSDate objects just fine. If you want to store time intervals, the date of the post must be converted to a time interval since some fixed reference date; you do that for example using "timeIntervalSinceReferenceDate". If you do that, I very strongly recommend that you don't call the variable "date" but something like "secondsSinceReferenceDate" which makes it obvious what to store when you are given a date, and how to convert that number back to an NSDate.
(The reason to call it "secondsSinceReferenceDate" is because there is plenty of code that tries to store milliseconds, or nanoseconds, and there is plenty of code that stores intervals since the epoch (Jan 1st 1970), so it's really good if someone reading your code knows immediately what the numbers mean by just looking at the variable name).

Related

How to save date field to Firebase using Swift?

I'm trying to save a date field to Firebase, but I'm getting an error.
#IBAction func dateValueChanged(sender: AnyObject) {
let datePicker = UIDatePicker()
datePicker.maximumDate = NSDate()
}
#IBAction func saveButtonTapped(sender: AnyObject) {
self.ref.child("New Posts").child(userID!).setValue(["Diary:":textEntry.text, "Title:": titleEntry.text, "Date:": datePicker.date])
}
Error message:
Contextual type 'AnyObject' cannot be used with dictionary literal
Any ideas what I'm not doing? Thanks.
I would recommend saving the date as Unix time (timeIntervalSince1970), though any standard date format should be fine.
Convert the NSDate to NSNumber to save. And from NSNumber to NSDate to read. But be aware if you ever read or write from an Android app, you will need to convert the numeric value to unix style Timestamp which defines the origin date (zero value) as 1970. iOS represents the baseline slightly differently.

How to set a UITextField.text to a NSDate?

I'm connecting to an API and when I get data back for dates it looks like this:
2016-07-05T21:39:17.696Z
How can I set a uitextfield.text to that date so it looks like a normal date (ie. 07/05/2016 or something similar)?
The tricky part is the NSDate is returned as a string from the API so it's not in the NSDate format to begin with.
A text field is only for editing freeform text, not dates. You can go one of two routes. If you intend for the user to be able to edit a date, then use a UIDatePicker to provide an interface specifically for editing dates. If you just want freeform text back, then you can convert a date to a string with NSDateFormatter.
try:
let formatter = NSDateFormatter()
let yourDate = NSDate()
formatter.dateStyle = NSDateFormatterShortStyle
formatter.timeStyle = NSDateFormatterNoStyle
self.textfield.text = formatter.stringFromDate(yourDate)

Get elements from array where date is today

I have an array of objects where a property is date of type NSDate. The array includes future days and past days.
I want to get an array of elements from that array that only includes dates that are in today, not the last 24 hours.
I ordered the elements by descending (new to old):
allDashboards.sortInPlace({ $0.date!.compare($1.date!) == NSComparisonResult.OrderedDescending
I tried to do a for loop, check if date is yesterday and cut the array there, but it doesn't work as it may be no element with a yesterdays date:
for dash in allDashboards {
if (NSCalendar.currentCalendar().isDateInYesterday(dash.date!)) {
print(i)
allDashboards.removeRange(Range.init(start: 0, end: i))
break
}
i += 1
}
Is there a method to see if date is past a day instead of if the date is part of that day?
One-liner:
let todayDashboards = allDashboards.filter { NSCalendar.currentCalendar().isDateInToday($0.date!) }
You can use NSDateComponents to create the dates which represent the start and end of your acceptable range. These can be anything you want.
Once you have those dates, you can create an NSPredicate which matches dates > the start and < the end dates. This will generate a filtered array for you.
You could use isDateInToday to filter the content too.
What you must not do is to iterate the array and mutate it at the same time, which is what your current code does with allDashboards.removeRange inside the for loop.
You can filter all dates which are today with the filter function and isDateInToday of NSCalendar
let filteredDashboards = allDashboards.filter{ NSCalendar.currentCalendar().isDateInToday($0.date!) }

Storing dates in CoreData - Convert date string to NSTimeInterval?

So I want to store dates in my CoreData entity and the model indicates the field should be of NSTimeInterval. Not sure why it's not NSDate though as NSTimeInterval sounds... odd.
From my JSON data source I have the following string: "2016-01-28T23:20:00" and I have no idea how to convert this to a NSTimeInterval. I can convert it to NSDate once I figure out the correct format, but that doesnt do much me much good.
Thanks!
You can store NSDate in CoreData Directly.
Update:
If you are using scalar propertie, convert like this:
// `NSTimeInterval` --> `NSDate`:
var date = NSDate(timeIntervalSinceReferenceDate: 123)
// `NSDate` --> `NSTimeInterval`:
var timeInterval = date.timeIntervalSinceReferenceDate

Core Data NSTimeInterval using an accessor directly is buggy

I'm setting an NSTimeInterval using setValueForKey within an NSManagedObject Subclass, the value gets set correctly, and is also correct when it is retrieved using valueForKey, however, if an accessor is used directly, it returns an incorrect value. Here is a code sample that demonstrates the issue
let date = NSDate() //NSTimeIntervalSince1970 = 1447054145.15281
self.setValueForKey(date, "dateLastSynced")
self.valueForKey("dateLastSynced") //= 1447054145.15281
self.dateLastSynced // !!ERROR Incorrect value = 468746945.152815
Strangely enough, if the dateLastSynced is converted to an NSDate, everything works perfectly.
Any ideas on whats happening?
A scalar property of type NSTimeInterval for a Core Data Date
property represents the time in seconds since the reference date
Jan 1, 2001. The Core Data generated accessor methods transparently
convert between NSTimeInterval and NSDate.
Therefore you set a value using the scalar accessor with
obj.dateLastSynced = date.timeIntervalSinceReferenceDate
and you retrieve the value with
let date = NSDate(timeIntervalSinceReferenceDate: obj.dateLastSynced)
This gives the same results as the Key-Value Coding methods
// Set:
obj.setValueForKey(date, "dateLastSynced")
// Get:
let date = obj.valueForKey("dateLastSynced")
Assigning to self.valueForKey("dateLastSynced") won't work; it's not an lvalue. You need to use setValueForKey.
Also, if the dateLastSynced is a date property, you cannot assign it a double value and expect it to work. Use
self.setValue(NSDate(timeIntervalSinceReferenceDate: <value>), forKey:"dateLastSynced")

Resources