I have a Cocoa application that records datestamps on events. I need to know when the system time is reset and by how much, but I can't seem to fine a notification anywhere that tells me such a thing has happened. This change could happen because NTP reset the clock or because the user reset (e.g. from System Preferences). It would be great if there was just a NSNotification
I could register to receive, but I'm open to any suggestions.
Apple added in NSSystemClockDidChangeNotification, part of NSDate, in Snow Leopard (10.6). There doesn't appear to be a way to do it in Leopard (10.5) or earlier. Per the Apple NSDate docs:
Posted whenever the system clock is changed. This can be initiated by a call to settimeofday() or the user changing values in the Date and Time Preference panel. The notification object is null. This notification does not contain a userInfo dictionary.
This doesn't appear to tell you "how much" time has changed. You could possibly calculate that by periodically (say, every 5 seconds in a NSTimer
) capturing the system time with [NSDate date]
, saving it into a variable, and then after NSSystemClockDidChangeNotification
fires, grab the new date and compare the two together using NSDate's timeIntervalSinceDate:
method to get the difference.
Not millisecond or even second accurate, but pretty close.
EDIT: See this post. You could possibly use the UpTime()
C command to grab the system uptime in CPU tics (which you can later convert to seconds). You could use this to figure out by how much time has changed (assuming no system restart or sleep). This works even if the system clock is changed by the user or network time protocol.
If some on is looking for solution know system date change change event from 10.4
OSStatus DateChangeEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
NSLog(@"Event received!\n");
return 0;
}
- (void)SystemTimeChangeHandler
{
EventTypeSpec eventType;
eventType.eventClass = kEventClassSystem;
eventType.eventKind = kEventSystemTimeDateChanged;
EventHandlerUPP eventHandlerUPP =
NewEventHandlerUPP(DateChangeEventHandler);
EventHandlerRef eventHandlerRef = NULL;
(void)InstallApplicationEventHandler(
eventHandlerUPP,
1,
&eventType,
self,
&eventHandlerRef);
}
Time moves constantly. A notification every time the current time changed would be a constant, CPU-soaking stream of notifications.
What you need to do is get the current time in your event handler—the one that receives the events you're datestamping. You get the current time by calling [NSDate date]
.
I don't think there's a single way to do that because of the different mechanisms by which the time could change. But it wouldn't be very expensive (too expensive? Don't know, have you profiled it yet? ;-) to set an NSTimer
once a second to check the time and compare it with the previous value. If it's not advanced by about a second, something interesting happened and you can notify your audit object.
© 2022 - 2024 — McMap. All rights reserved.