Im currently working on a android application.. I have to log the accelerometer sensor event coordinate with event time. I got the sensor event timestamp like "3497855005850" but i am not able to convert event timestamp into user readable date time format.Thanks in advance
How can i convert SensorEvent timestamp to unix timestamp?
The sensor timestamp is actually nanoseconds of uptime, not system time in nanoseconds. See SensorEvent.timestamp to absolute (utc) timestamp? .
In theory, you can convert sensor timestamp to time in milliseconds using:
long timeInMillis = (new Date()).getTime()
+ (sensorEvent.timestamp - System.nanoTime()) / 1000000L;
You could even bracket the (new Date()).getTime()
call with two System.nanoTime()
calls and average them to get closer to the actual offset.
Then you can format the sensor time as date and time.
You can set referent time variables in your onSensorChanged(SensorEvent)
function.
Reference for current time and event time. When event arrives subtract sensor referent time from event time and you will have difference in nanoseconds. You can add that difference divided by 1,000,000 to current time reference to get event time in milliseconds.
Error with calculating this can be max 0.5 milliseconds for one event. You can minimize error by changing referent times occasionally.
private long sensorTimeReference = 0l;
private long myTimeReference = 0l;
public void onSensorChanged(SensorEvent event) {
// set reference times
if(sensorTimeReference == 0l && myTimeReference == 0l) {
sensorTimeReference = event.timestamp;
myTimeReference = System.currentTimeMillis();
}
// set event timestamp to current time in milliseconds
event.timestamp = myTimeReference +
Math.round((event.timestamp - sensorTimeReference) / 1000000.0);
// some code...
}
The official SensorEvent#timestamp
documentation states:
[event.time is] The time in nanoseconds at which the event happened. For a given sensor, each new sensor event should be monotonically increasing using the same time base as SystemClock.elapsedRealtimeNanos() .
Challenge
SystemClock.currentTimeNanos()
instead (eg Nexus 4).Device-independent solution:
/**
* Calculates the static offset (ms) which needs to
* be added to the `event.time` (ns) to get the Unix
* timestamp of the event.
*
* @param eventTimeNanos the {@code SensorEvent.time} to be used to determine the time offset
* @return the offset in milliseconds
*/
private long eventTimeOffset(final long eventTimeNanos) {
// Capture timestamps of event reporting time
final long elapsedRealTimeMillis = SystemClock.elapsedRealtime();
final long upTimeMillis = SystemClock.uptimeMillis();
final long currentTimeMillis = System.currentTimeMillis();
// Check which timestamp the event.time is closest to the event.time
final long eventTimeMillis = eventTimeNanos / 1_000_000L;
final long elapsedTimeDiff = elapsedRealTimeMillis - eventTimeMillis;
final long upTimeDiff = upTimeMillis - eventTimeMillis;
final long currentTimeDiff = currentTimeMillis - eventTimeMillis;
// Default case (elapsedRealTime, following the documentation)
if (Math.abs(elapsedTimeDiff) <= Math.min(Math.abs(upTimeDiff), Math.abs(currentTimeDiff))) {
final long bootTimeMillis = currentTimeMillis - elapsedRealTimeMillis;
return bootTimeMillis;
}
// Other seen case (currentTime, e.g. Nexus 4)
if (Math.abs(currentTimeDiff) <= Math.abs(upTimeDiff)) {
return 0;
}
// Possible case, but unknown if actually used by manufacturers (upTime)
throw new IllegalStateException("The event.time seems to be upTime. In this case we cannot use a static offset to calculate the Unix timestamp of the event");
}
Registration time delay
event.time
and the time at which the sensor event listener is triggered (registration time) as we only use the SystemClock
to calculate the offset.Regarding "Possible Case" (see code):
It's unknown if any manufacturer actually uses the upTime
as event.time
. Thus, we throw an exception to see if this actually ever happens.
If this happens and if we calculate a static offset between currentTime
and upTime
this would lead to time shifts when the device is in (deep) sleep again. We would need to calculate the offset dynamically for each event which is quite heavy.
If this happens on devices this could be tested using: https://developer.android.com/training/monitoring-device-state/doze-standby#testing_doze_and_app_standby
https://source.android.com/devices/sensors/hal-interface.html#sensors_event_t
"timestamp must be synchronized with the elapsedRealtimeNano clock" so
val timeInMills = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000
I had the same problem and used ehartwell's solution . However I used System.currentTimeMillis()
instead of new Date().getTime()
.
Furthermore I found that there is an offset of sensorEvent.timeStamp
and System.nanoTime()
of maximal 300 ms, mostly < 200 ms. Depending on the needed accuracy you can ignore this difference.
If I use Boban S. solution , the difference is correct at the initialisation. However, the correct time and the time of the measurements diverge. The estimated time of the measurements is in the future.
I see three ways to get millis (Kotlin)
val millis = Date().getTime() + (event.timestamp - System.nanoTime()) / 1000000L
val millis = System.currentTimeMillis() + (event.timestamp - System.nanoTime()) / 1000000L
val millis = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000L
all three deliver same result, but when I want to see diff from calculated value to current time
val diff = System.currentTimeMillis() - millis
I see 'diff' with value -359704905 ?
Log.d("diff", "" + event.timestamp + " - " + System.nanoTime())
diff: 541695268300000 - 181990403666592
diff: 541695277240000 - 181990405818592
diff: 541695286859000 - 181990411901592
diff: 541695296139000 - 181990412584592
diff: 541695305735000 - 181990415222592
So all suggested solution are not right
for me this simple way fits my needs
override fun onSensorChanged(sensorEvent: SensorEvent?) {
val millis = System.currentTimeMillis()
}
It varies for each device. It could be based on epoch, time since boot, and CPU awake time. Best approach is to read all three, then see which one the timestamp is closest to, then convert based on the offset.
SensorEvent.timestamp
is when the event happened, but it is an elapsed time since boot. It is not absolute time. We want to convert it into absolute time.
Reference: https://developer.android.com/reference/android/hardware/SensorEvent#timestamp
Millis
here.System.currentTimeMillis()
b) SystemClock.elapsedRealtime()
and c) SensorEvent.timestamp
SystemClock.elapsedRealtimeNanos()
, then we need to convert it into Millis
as below:val systemCurrentTimeMillis = System.currentTimeMillis()
val systemClockElapsedRealtimeMillis = TimeUnit.NANOSECONDS.toMillis(SystemClock.elapsedRealtimeNanos())
val sensorEventTimeStampMillis = TimeUnit.NANOSECONDS.toMillis(sensorEvent.timestamp)
systemCurrentTimeMillis
, and systemClockElapsedRealtimeMillis
as below:val currentMinusElapsedRealtimeMillis = systemCurrentTimeMillis - systemClockElapsedRealtimeMillis
sensorEventTimeStampMillis
to it as below:val actualEventTimeMillis = currentMinusElapsedRealtimeMillis + sensorEventTimeStampMillis
Joda Time
):val actualEventTimeUtc = DateTime(actualEventTimeMillis, DateTimeZone.UTC)
The actualEventTimeUtc
is the absolute time when the event happened.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.