CMLogItem timestamp: Why so complicated? - swift

I receive a CMLogItem from a CoreMotion query in swift (could be accelerometer, gyroscope). Now, I want to get the timestamp of that sample, preferably as a Date() object. CMLogItems have a property .timestamp of type TimeInterval.
The documentation tells me the following:
The CMLogItem class defines a read-only timestamp property that
records the time a motion-event measurement was taken.
However, I am not sure how to convert this timestamp to a Date() object because I dont know what the timestamp is referring to.
Another documentation says:
The timestamp is the amount of time in seconds since the device
booted.
But this seems really weird and I dont understand why apple would create such an inconsistent and complicated API.

Proper answer is:
extension CMLogItem {
static let bootTime = Date(timeIntervalSinceNow: -ProcessInfo.processInfo.systemUptime)
func startTime() -> Date {
return CMLogItem.bootTime.addingTimeInterval(self.timestamp)
}
}
This gives us stable, monotonic results, which is not a case, when bootTime is computed every time startTime is called.

I think I figured it out.
The documentation is just wrong here.
It is not the "time in seconds since the device booted" — it is indeed the time since their reference date.
Fix:
extension CMLogItem {
func startTime() -> Date {
#if os(watchOS)
return Date(timeIntervalSinceReferenceDate: self.timestamp)
#else
let systemRebootTime = Date(timeIntervalSinceNow: -ProcessInfo.processInfo.systemUptime)
return systemRebootTime.addingTimeInterval(self.timestamp)
#endif
}
}

Related

NSCalendar.startOfDayForDate(date:) equivalent for iOS 7 with non-optional return type

Is it possible to change an NSDate object so that the result is equivalent to NSCalendar.startOfDayForDate(date:)? That method is only available to iOS 8 and newer, but I am looking for something that works on iOS 7.
I have looked at two methods:
NSCalendar.dateFromComponents(comps:) as described here: NSDate beginning of day and end of day. For instance, like this:
class func startOfDay(date: NSDate, calendar: NSCalendar) -> NSDate {
if #available(iOS 8, *) {
return calendar.startOfDayForDate(date)
} else {
let dateComponents = calendar.components([.Year, .Month, .Day], fromDate: date)
return calendar.dateFromComponents(dateComponents)!
}
}
NSDateFormatter.dateFromString(string:) by way of
stringFromDate(date:), i.e. converting the NSDate object into a string without the time, then converting it back into an NSDate object.
The problem with both methods is that they return an optional NSDate. I am reluctant to unwrap this implicitly and I’d rather avoid changing the return type of the method within which these methods are called.
I think the calendar.components() method returns an optional, because you can theoretically enter components that do not create valid date, like 2000-02-30. If, as in your case, the components already come from a valid date, I would not be reluctant to implicitly unwrap the optional.

In Swift what exactly is the difference between a function that returns a value and one that does not?

Here is some code that I am using in my program
func getDate() {
getTimeRightNow()
date = timeRightNow
sendDate()
print("date was sent")
}
func getTimeRightNow() {
timeRightNow = NSDate().timeIntervalSince1970
}
The function getDate() calls getTimeRightNow() which then gets the current NSDate and sets it equal to a variable timeRightNow. I then take timeRightNow and set date equal to it which I then pass along for further use.
Below, I have a second version. This time I instead have the getTimeRightNow() function return a value of type Double...
func getDate() {
date = getTimeRightNow()
sendDate()
print("date was sent")
}
func getTimeRightNow()-> Double {
timeRightNow = NSDate().timeIntervalSince1970
return timeRightNow
}
Both versions seems to work exactly the same. I guess the second version lets me type one less line, is that the only advantage that it offers? Is the second version considered "best practice"? In the second version, is there any chance that the sendDate() function gets called BEFORE the getTimeRightNow() function finishes and sets a value for date? How about in the first version, is there any chance that timeRightNow gets set equal to date BEFORE the getTimeRightNow() function finishes and sets a proper NSDate for timeRightNow?
Having trouble understanding this, appreciate the help
The difference between the function that has a return value and one that does not is that it returns a value. That can be really practical.
let aDate = myRandomDate()
let anotherDate = myRandomDate()
You would not be able to do this with a function that does not return a value.

Getting the current time as a decimal point number

I want to be able to get the current time as a decimal point number so it can be used. so for example if the time is 13:46 I want to get it as 13.46
It seems simple but I am struggling getting to it.
We can use an NSDateFormatter to do exactly this:
extension NSDate {
func currentTime() -> String {
let formatter = NSDateFormatter()
formatter.dateFormat = "HH.mm"
return formatter.stringFromDate(self)
}
}
And now we just use it by calling it on any instance of NSDate:
let now = NSDate()
print(now.currentTime())
you can stringify the time and serch lastindexOf(":") and substitue it with a "."
UPDATE
I don't really catch what program language are you using, but it's plenty of library for stringify object so if you have a 13:46 you can convert it to String and, in the same string library you could find the method lastIndexOf(char). But if you don't find it you can always write following this concepts:
String are an array of Char so you can cycle it and convert the char in that position in the char you need.

Using customized setter/getter and initializing the property for a swift date

I have a class called Trip which has an NSDate property called date. My desire is to make sure that the date property always has the time value set to the beginning of the day. I do this by:
Creating an NSCalendar constant called calendar so that I can use the startOfDayForDate method to reset the date value.
Creating a custom setter method for the date property that calls the startOfDayForDate method.
However, I want to initialize the date property to the start of today's date.
The code that I have so far is shown below.
class Trip {
private let calendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var date: NSDate {
get {
return self.date
}
set {
self.date = calendar.startOfDayForDate(newValue)
}
}
}
This code a) doesn't initialize the date property and b) (I discovered) results in an infinite loop when the setter is called. Upon further research, I believe that customized getters/setters are strictly computed, right?
How do I accomplish what I mentioned earlier:
a.) making sure that sets to the date property reset to the start of the day and
b.) initializing the date property to the start of today's date?
I think you want to have a date that will always be the start of the date. Replace your current date variable with this:
private var privateDate = NSDate()
var date: NSDate {
get {
return privateDate
}
set {
privateDate = calendar.startOfDayForDate(newValue)
}
}
There may be a slightly better way to do this, but I'm guessing your application won't have tens of thousands of your Trip class, so you should be fine.

Swift ios date as milliseconds Double or UInt64?

I'm not iOS developer but started learning Swift.
I try to convert some logic from Android project to iOS.
I have the following method:
func addGroupItemSample(sample : WmGroupItemSample){ // some custom class
var seconds: NSTimeInterval = NSDate().timeIntervalSince1970
var cuttDate:Double = seconds*1000;
var sampleDate: UInt64 = sample.getStartDate(); // <-- problematic place
if(sampleDate > cuttDate){
// ....
}
}
From the method above you can see that sample.getStartDate() returns type UInt64.
I thought it's like long in Java: System.currentTimeMillis()
But current time in milliseconds defined as Double.
Is it a proper way to mix Double and UInt64 or do I need to represent all milliseconds as Double only?
Thanks,
in iOS it is better to use double, but if you want to easy port your code and keep it consistent you can try this:
func currentTimeMillis() -> Int64{
let nowDouble = NSDate().timeIntervalSince1970
return Int64(nowDouble*1000)
}
Swift does not allow comparing different types.
seconds is a Double floating point value in seconds with sub-second accuracy.
sampleDate is a UInt64 but the units are not given.
sampleDate needs be converted to a Double floating point value with units of seconds.
var sampleDate: Double = Double(sample.getStartDate())
Then they can be compared:
if(sampleDate > cuttDate){}
Here's an alternative version, for Swift 3:
/// Method to get Unix-style time (Java variant), i.e., time since 1970 in milliseconds. This
/// copied from here: http://stackoverflow.com/a/24655601/253938 and here:
/// http://stackoverflow.com/a/7885923/253938
/// (This should give good performance according to this:
/// http://stackoverflow.com/a/12020300/253938 )
///
/// Note that it is possible that multiple calls to this method and computing the difference may
/// occasionally give problematic results, like an apparently negative interval or a major jump
/// forward in time. This is because system time occasionally gets updated due to synchronization
/// with a time source on the network (maybe "leap second"), or user setting the clock.
public static func currentTimeMillis() -> Int64 {
var darwinTime : timeval = timeval(tv_sec: 0, tv_usec: 0)
gettimeofday(&darwinTime, nil)
return (Int64(darwinTime.tv_sec) * 1000) + Int64(darwinTime.tv_usec / 1000)
}
func get_microtime() -> Int64{
let nowDouble = NSDate().timeIntervalSince1970
return Int64(nowDouble*1000)
}
Working fine
Simple one-line code to get time token in UInt64
let time = UInt64(Date().timeIntervalSince1970 * 1000)
print(time) <----- prints time in UInt64
Additional tip:
Looking for timestamp with 10 Digit milliseconds since 1970 for API call then
let timeStamp = Date().timeIntervalSince1970
print(timeStamp) <-- prints current time stamp