How can I get notified of a system time change in my Cocoa application?
Asked Answered
V

4

11

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.

Volition answered 27/3, 2009 at 15:55 Comment(2)
DO you mean when the clock changes, e.g. by an NTP sync, or changing the time zone or manually setting the time in System Preferences?Lebron
Yes, that is what I mean. I'm sorry that I was not very clear to begin with. I've hopefully made this clearer now.Volition
P
18

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.

Photoelectrotype answered 26/10, 2009 at 2:39 Comment(0)
J
11

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);

}

Joppa answered 29/7, 2010 at 14:8 Comment(0)
I
1

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].

Indebtedness answered 27/3, 2009 at 16:24 Comment(1)
Well, isnt it obvious that the OP means an unusual change of time and not the regular advancement of the clock :)Doug
L
0

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.

Lebron answered 27/3, 2009 at 20:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.