0

I'm trying to figure out how to edit the time and the 'Set Date and Time Automatically' check box programmatically. I've spent a while and cant find the solution.

I've tried looking at the NSUserDefault keys but don't see them.

NSLog(@"%@", [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys]);

help appreciated. This is OSX (not iphone).

Miek
  • 1,127
  • 4
  • 20
  • 35
  • You have three different questions in one. And the reason I say that is because there is no straight way to accomplish all. Also, you asked about changing the time zone which you already know how to do. I say edit your question to be simple and straight forward. – Black Frog Apr 14 '15 at 02:04

2 Answers2

1

This is not a complete answer. I just code below will just change the system time. Note: changing the system time requires root permission. Running the code via Xcode IDE as is will fail. Running from Terminal using sudo command works.

//
//  main.m
//  TimeChange
//
//  Created by ... on 4/13/15.
//  Copyright (c) 2015 .... All rights reserved.
//

#import <Foundation/Foundation.h>
#import <sys/time.h>
#include <errno.h>

extern int errno;

void NSLogTime(const struct tm *restrict temp, suseconds_t microseconds)
{
    char tmbuf[64], buf[64];
    strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", temp);
    snprintf(buf, sizeof buf, "%s.%06d\n", tmbuf, microseconds);
    NSLog(@"   %@", [[NSString alloc] initWithUTF8String:buf]);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Built from samples based on the URL listed below
        // http://stackoverflow.com/questions/2408976/struct-timeval-to-printable-format
        // http://www.linuxquestions.org/questions/programming-9/c-code-to-change-date-time-on-linux-707384/

        // Do whatever you need to set the following variable
        // In this example I am hard-coding it
        int month = 2;
        int day = 27;
        int year = 2002;

        NSLog(@"Getting current date/time...");
        struct timeval currentTime;
        int success = gettimeofday(&currentTime, 0); // should check for success
        struct tm *localTime = localtime(&currentTime.tv_sec);

        NSLogTime(localTime, currentTime.tv_usec);

        if (localTime)
        {
            NSLog(@"...create new date/time structure...");
            localTime->tm_mon  = month - 1;
            localTime->tm_mday = day;
            localTime->tm_year = year - 1900;

            const struct timeval tv = {mktime(localTime), 0};
            success = settimeofday(&tv, 0);

            // check if we are success
            if (success == 0)
            {
                NSLog(@"...time was changed!");

                // get the new time from the system and display it
                struct timeval updatedTime;
                gettimeofday(&updatedTime, 0); // should check for success
                NSLogTime(localtime(&updatedTime.tv_sec), updatedTime.tv_usec);
            }
            else
            {
                // display the error message
                NSLog(@"Error Setting Date: %s", strerror(errno));
            }
        }

    }
    return 0;
}

Below is screen shot of the coding running in the terminal.

TimeChange running

Note: the one hour time difference in the output is because Daylight Saving Time (DST) was not in-effect back in Feb 22, 2002.

Black Frog
  • 11,595
  • 1
  • 35
  • 66
1

So I discovered that I could write an applescript that would execute bash script commands. Then I called the script with NSApplescript. The cool thing is apple script has an elegant password dialog and it only needs to be handled once for everything. This is far nicer than making the terminal appear.

The downside was the process for calling the applescript with NSApplescript. What should have been a simple process of passing 3 args to the script needed to be handled by about 50 lines of outdated NSAppleEvent code that didn't even work in Apples docs. Luckily, I found a post where someone knew the constants missing from the absent Carbon framework.

The Code:

// Caller responsible for well formed ip address.
+(BOOL)setDateAndTimePreferences:(NSString*)ipAddress setAutoNetworkTime:(BOOL)yNo withTimezone:(NSString*)timezone{

    // Load the script from a resource by fetching its URL from within our bundle
    // Note: if the script if stored in a nother file location, NSBundle may not be
    // necessary. Make sure the path to the script is correct.
    NSString* path = [[NSBundle mainBundle] pathForResource:@"date_time_pref" ofType:@"scpt"];
    if (path != nil){

        NSURL* url = [NSURL fileURLWithPath:path];
        if (url != nil)
        {
            NSDictionary* errors = [NSDictionary dictionary];
            NSAppleScript* appleScript =
            [[NSAppleScript alloc] initWithContentsOfURL:url error:&errors];
            if (appleScript != nil)
            {

                // Get the value of the setAutoNetwork checkbox.
                NSString *chkBox = (yNo == YES)? @"on": @"off";

                // Create the arg parameters
                NSAppleEventDescriptor* firstParameter =
                [NSAppleEventDescriptor descriptorWithString:ipAddress];

                NSAppleEventDescriptor* secondParameter =
                [NSAppleEventDescriptor descriptorWithString:chkBox];

                NSAppleEventDescriptor* thirdParameter =
                [NSAppleEventDescriptor descriptorWithString:timezone];

                // Create and populate the list of parameters.
                NSAppleEventDescriptor* parameters = [NSAppleEventDescriptor listDescriptor];
                [parameters insertDescriptor:firstParameter atIndex:1];
                [parameters insertDescriptor:secondParameter atIndex:2];
                [parameters insertDescriptor:thirdParameter atIndex:3];

                // Create the AppleEvent target
                ProcessSerialNumber psn = {0, kCurrentProcess};
                NSAppleEventDescriptor* target = [NSAppleEventDescriptor
                                              descriptorWithDescriptorType:typeProcessSerialNumber
                                              bytes:&psn length:sizeof(ProcessSerialNumber)];

                //  We need these constants from the Carbon OpenScripting
                // framework, but we don't actually need Carbon.framework.
                #define kASAppleScriptSuite 'ascr'
                #define kASSubroutineEvent  'psbr'
                #define keyASSubroutineName 'snam'

                // Create an NSAppleEventDescriptor with the script's method name to call,
                // this is used for the script statement: "on   set_preferences(arg1,arg2arg3)"
            // Note that the routine name must be in lower case.
            NSAppleEventDescriptor* handler =
            [NSAppleEventDescriptor descriptorWithString:
             [@"set_preferences" lowercaseString]];

            // Create the event for an AppleScript subroutine,
            // set the method name and the list of parameters
            NSAppleEventDescriptor* event =
            [NSAppleEventDescriptor  appleEventWithEventClass:kASAppleScriptSuite
                                                     eventID:kASSubroutineEvent
                                            targetDescriptor:target
                                                    returnID:kAutoGenerateReturnID
                                               transactionID:kAnyTransactionID];
            [event setParamDescriptor:handler forKeyword:keyASSubroutineName];
            [event setParamDescriptor:parameters forKeyword:keyDirectObject];

                // call the event in AppleScript
                if (![appleScript executeAppleEvent:event error:&errors])
                {
                    // report any errors from 'errors'
                    NSLog(@"Errors %@",[errors description]);
                }

                [appleScript release];
            }

            else{
                // report any errors from 'errors'
                NSLog(@"Error: applescript is nil");
            }

        }else{

            NSLog(@"Could not locate the time_date_preferences script");
            return NO;
        }

    }else{

        NSLog(@"Could not locate the time_date_preferences script");
        return NO;
    }



    return YES;

}

The Script:

on set_preferences(ipaddress, chkbox, timezone)

    global timezonelist

    do shell script "/usr/sbin/systemsetup -setusingnetworktime " & chkbox password "passwordhere" with administrator privileges
    do shell script "/usr/sbin/systemsetup -setnetworktimeserver " & ipaddress with administrator privileges
    set timezonelist to (do shell script "/usr/sbin/systemsetup -listtimezones" with administrator privileges)

    if timezonelist contains timezone then
        do shell script "/usr/sbin/systemsetup -settimezone " & timezone with    administrator privileges

    else

        display notification "Please open Date and Time Preferences and set your time zone manually." with title ("Invalid Time Zone")
       delay 1
    end if

end set_preferences
Miek
  • 1,127
  • 4
  • 20
  • 35