Skip to main content
Question

Time Zone using Current Location scriptable?


Forum|alt.badge.img+10
  • Contributor
  • 200 replies

I'm looking for a programatic way to be able to set that setting in Date & Time. Any ideas?

36 replies

Forum|alt.badge.img+26
  • Valued Contributor
  • 907 replies
  • March 15, 2013

The ability to use "Current Location" would be a great, but if it helps you as to what we do to set the timezone, I will gladly expound. We are all in the American Eastern Time Zone so I hardcode for "America/New_York"

We also have Network Time Servers at each of our locations. So to set both the timezone via command line on our images, I have a script that runs the following two commands:

systemsetup -settimezone "America/New_York"
systemsetup -setnetworktimeserver "yourntpserver.yourdomainhere.com"

So, now that we have the syntax of the commands covered, let me start the skeleton of a script for you...knowing that I lack the knowledge of how to finish this concept. If nothing else, this should give you some food for thought:

#!/bin/sh

###Variable Declaration###
#This is my main challenge. How do write a command(s) that will
#populate this variable by either pulling the network segment or 
#Casper location data for a given Mac in the data base, and then how 
#do we transform what is pulled from the database into something
#systemsetup understands such as 'America/New_York' or say 'Europe/Berlin'.

TimeZone="`<hoped for command the populates this variable here>`"

systemsetup -settimezone "$TimeZone"

exit 0

Hopefully some better scripters weigh in on this...and who knows...maybe there is a way to set it using "Current Location", but the man page for the systemsetup command does not cover that.


Forum|alt.badge.img+10
  • Author
  • Contributor
  • 200 replies
  • March 15, 2013

Further investigation on my 10.8.3 computer yielded that the actual file being touched is /Library/Preferences/com.apple.timezone.auto.plist I wonder if it's touching other files as well.

Time to fire up PlistBuddy to try to script it.


Forum|alt.badge.img+15
  • Valued Contributor
  • 118 replies
  • April 18, 2013

As always TEST TEST TEST in a dev environment first.
This works for me. It only seems to do the first lookup after opening the Date & Time prefs.

#!/bin/sh

# Use "/usr/sbin/systemsetup -listtimezones" to see a list of available list time zones.
TimeZone="America/New_York"
TimeServer="time.apple.com"

############# Pause for network services #############
/bin/sleep 10
#################################################

/usr/sbin/systemsetup -setusingnetworktime off 

#Set an initial time zone
/usr/sbin/systemsetup -settimezone $TimeZone

#Set specific time server
/usr/sbin/systemsetup -setnetworktimeserver $TimeServer

# enable location services
/bin/launchctl unload /System/Library/LaunchDaemons/com.apple.locationd.plist
uuid=`/usr/sbin/system_profiler SPHardwareDataType | grep "Hardware UUID" | cut -c22-57`
/usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.$uuid LocationServicesEnabled -int 1
/usr/sbin/chown -R _locationd:_locationd /var/db/locationd
/bin/launchctl load /System/Library/LaunchDaemons/com.apple.locationd.plist

# set time zone automatically using current location 
/usr/bin/defaults write /Library/Preferences/com.apple.timezone.auto Active -bool true

/usr/sbin/systemsetup -setusingnetworktime on 

/usr/sbin/systemsetup -gettimezone
/usr/sbin/systemsetup -getnetworktimeserver

exit 0

Forum|alt.badge.img+10
  • Author
  • Contributor
  • 200 replies
  • December 18, 2013

Just to answer my own question here's what I've come up with, pretty or elegant? No. Effective? Seems to be.

#!/bin/bash uuid=/usr/sbin/system_profiler SPHardwareDataType | grep "Hardware UUID" | cut -c22-57 /bin/launchctl unload /System/Library/LaunchDaemons/com.apple.locationd.plist /usr/bin/defaults write /private/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.$uuid LocationServicesEnabled -int 1 /usr/bin/defaults write /private/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.notbackedup.$uuid LocationServicesEnabled -int 1 /usr/sbin/chown -R _locationd:_locationd /var/db/locationd /bin/launchctl load /System/Library/LaunchDaemons/com.apple.locationd.plist exit 0

For Auto Time Zone similar idea

#!/bin/sh /usr/bin/sudo /usr/bin/defaults write /Library/Preferences/com.apple.timezone.auto Active -bool True exit 0

Forum|alt.badge.img+1
  • New Contributor
  • 7 replies
  • April 27, 2015

@ericbenfer Thanks for the TimeServer, TimeZone, Location Service on script. It was everything I needed!


bpavlov
Forum|alt.badge.img+18
  • Esteemed Contributor
  • 1206 replies
  • May 28, 2015

I was actually looking at this myself. Am I right in that this only works after opening up Date and Time? There's got to be a way to kick off the "Determining location..." portion that the System Preference pane. I'll be looking a bit more into this, but figured I'd ask.


bpavlov
Forum|alt.badge.img+18
  • Esteemed Contributor
  • 1206 replies
  • May 29, 2015

I just want to describe a few other things I tried in investigating this. I went ahead and implemented the script as is. Ran command in Terminal:

opensnoop -v

and then opened up Date and Time preferences

Lots of stuff going on but the main ones I saw were TimeZoneToAdmin, timezoned, locationd, and references to GeoKit.framework. Most of it was located in here: /System/Library/PreferencePanes/DateAndTime.prefPane/Contents/Resources/TimeZone.prefPane/Contents/Resources/timezoned.app

Unfortunately, I didn't get much further than that. Unloading and re-loading the plist doesn't seem to do much either. Tried looking at Developer documentation for anything related to timezone settings and there are references to Core Location services but I wouldn't know what to do with that at this point in time.

But here's what I discovered which I find rather interesting: if you disable and re-enable wireless it automatically re-syncs after a 2-3 seconds (this assumes it reconnects to a wireless network with an active internet connection). Doesn't work with Ethernet. I'm wondering if disabling the wireless and re-enabling the wireless as part of the script would automatically sync to the right timezone. The downside is if the computer only has a wireless connection and for whatever reason cannot reconnect to the network (and therefore the JSS) you may run into logs for the policy not completing successfully. Something to think about.


bpavlov
Forum|alt.badge.img+18
  • Esteemed Contributor
  • 1206 replies
  • May 29, 2015

Running a simple commands of:

/usr/sbin/networksetup -setairportpower en0 off
/usr/sbin/networksetup -setairportpower en0 on

This assumes your wireless is en0. If it's not, you can run this command to determine what device name is listed as:

/usr/sbin/networksetup -listallhardwareports

Alternatively you can also use the Hardware Port name too:

/usr/sbin/networksetup -setairportpower Wi-Fi off
/usr/sbin/networksetup -setairportpower Wi-Fi on

But that may differ depending on the OS you're running. I think it was AirPort at one point and may have changed in either 10.7 or 10.8 to Wi-Fi.

Anyways this is all informational. I'll personally let OS naturally detect it either on a restart which a user is bound to do or when they connect to the wireless for the first time.


Forum|alt.badge.img+1
  • New Contributor
  • 1 reply
  • October 2, 2015

I found that this change would only be respected if the plist file was in xml format. Weird, huh?

This is my setup for enabling location-based time zone (Note; location services need to also be enabled, as above:

/bin/rm /Library/Preferences/com.apple.timezone.auto.plist
/usr/bin/defaults write /Library/Preferences/com.apple.timezone.auto Active -bool true
/usr/bin/plutil -convert xml1 /Library/Preferences/com.apple.timezone.auto.plist

Forum|alt.badge.img+7
  • Contributor
  • 90 replies
  • January 13, 2016

What worked for me is to create a package using composer containing the com.apple.timezone.auto.plist set to true. I then pushed this out via policy and added it to our Casper Imaging configuration.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict> <key>Active</key> <true/>
</dict>
</plist>


ncworster
Forum|alt.badge.img+7
  • New Contributor
  • 12 replies
  • February 23, 2017

Thanks @ericbenfer ! Worked great for me.


Forum|alt.badge.img+9
  • Contributor
  • 57 replies
  • March 16, 2017

So the script itself works for me but the problem that I'm seeing is that this will only set the timezone to Eastern but if the person sits in the Pacific timezone then it won't update the time on the machine until after they've launched the Date & Time preference pane. Is there any way to get the time zone to set itself correctly based off their geo automatically?


Forum|alt.badge.img+14
  • Contributor
  • 74 replies
  • July 6, 2017

@cgiordano I ran into the same problem - we were previously unloading and loading the LaunchD located in /System/Library/LaunchDaemons/com.apple.locationd.plist to get the change to stick, but SIP in Sierra neutered that. Finally had some time to dig in today and found this little gem that forces the auto timezone if you've set all the other stuff properly for automatic timezone discovery and enabling Location Services.

Since the bulk of the auto timezone stuff is a shell script and the above is in Python, I just loaded it in as a heredoc after all the bash code:

/usr/bin/python << EOF
from Foundation import NSBundle
TZPP = NSBundle.bundleWithPath_("/System/Library/PreferencePanes/DateAndTime.prefPane/Contents/Resources/TimeZone.prefPane")
TimeZonePref          = TZPP.classNamed_('TimeZonePref')
ATZAdminPrefererences = TZPP.classNamed_('ATZAdminPrefererences')

atzap  = ATZAdminPrefererences.defaultPreferences()
pref   = TimeZonePref.alloc().init()
atzap.addObserver_forKeyPath_options_context_(pref, "enabled", 0, 0)
result = pref._startAutoTimeZoneDaemon_(0x1)
EOF

Forum|alt.badge.img+12

Hey Guys!

Correct me if I'm wrong - the issue is not that the script doesn't work anymore. It's that Location Services have to be enabled for the automatic Date & Time function to work.

I am able to enable Location Services with the following bit of stuff in a 1st run script in the most up-to-date version macOS 10.12:

hdwruid=$(/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/awk '/Hardware UUID/{print $NF}')
loginfo "Hardware UUID: $hdwruid"
loginfo "enabling Location Services..."
osref=$(/usr/bin/sw_vers -productVersion | /usr/bin/awk -F. '{print $2}')

locd_osx(){
/bin/rm -rf /private/var/db/locationd/Library/Preferences/ByHost/*
/usr/bin/defaults write /private/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd."$hdwruid" LocationServicesEnabled -int 1
/usr/sbin/chown -R _locationd:_locationd /private/var/db/locationd
}

locd_macos(){
osbld=$(/bin/cat /System/Library/CoreServices/SystemVersion.plist | /usr/bin/sed -n 's/^[[:space:]]//g;6p')
osnam=$(/bin/cat /System/Library/CoreServices/SystemVersion.plist | /usr/bin/sed -n 's/^[[:space:]]//g;10p')
osvrs=$(/bin/cat /System/Library/CoreServices/SystemVersion.plist | /usr/bin/sed -n 's/^[[:space:]]//g;12p')
osstr=$(echo "$osnam$osvrs/$osbld" | /usr/bin/sed 's/<[^>]*>//g')
/bin/rm -rf /private/var/db/locationd/Library/Preferences/ByHost/*
locsrvc
/usr/bin/defaults write /private/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd."$hdwruid".plist LocationServicesEnabled -int 1
/usr/sbin/chown -R _locationd:_locationd /private/var/db/locationd/
/bin/chmod 600 /private/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd."$hdwruid".plist
}

if [ "$osref" -le 11 ]
then
    locd_osx
else
    locd_macos
fi

It might be a little bit of overkill to repopulate the .plist but this has worked for me since, like, forever.


Forum|alt.badge.img+14
  • Contributor
  • 74 replies
  • July 6, 2017

Hiya @brock.walters -- the issue we had run into is that we had bundled all this up in a Self Service job for our users who are traveling, and even after enabling location services and writing to the proper plists to set timezone auto adjust (code below), we were no longer able to unload/reload the com.apple.locationd.plist to enact the change in Sierra with SIP enabled. Opening up System Preferences and selecting the Time Zone radio button in Date & Time seemed to wake the system up and force it to detect that it should be setting TZ automatically, but I had difficulty until I came across that Python code above determining a way to do this with no user interaction and no restart.

  # Enable location services and enforce ownership; path is no longer UUID dependent in Sierra
  /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -int 1
  /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.notbackedup. LocationServicesEnabled -int 1
  /usr/sbin/chown -R _locationd:_locationd /var/db/locationd

  # Update Time Zone preference to auto-adjust based upon location
  /usr/bin/defaults write /Library/Preferences/com.apple.timezone.auto Active -bool YES
  /usr/bin/defaults write /Library/Preferences/com.apple.locationmenu ShowSystemServices -bool YES

Forum|alt.badge.img+9
  • Contributor
  • 57 replies
  • July 6, 2017

@NoahRJ That's an interesting find...What does your final script look like if you don't mind my asking?

@brock.walters My use case is the same as Noah's if we have users that travel the time zone doesn't always automatically update so forcing a check-in for the time server would seem to be the way to go. We'd rather walk them through running a policy in Self Service as opposed to having to walk them through opening the Date & Time System Preference.


Forum|alt.badge.img+14
  • Contributor
  • 74 replies
  • July 7, 2017

@cgiordano Sure thing - full script is below:

#!/bin/sh

#Get device interface for wireless
WiFiDI=$(/usr/sbin/networksetup -listallhardwareports | grep -A1 Wi-Fi | grep Device | awk '{print $2}')

#Get the version of Mac OS
OS_Version=$(sw_vers -productVersion)

if [[ $OS_Version == 10.11* ]]; then
  uuid=$(/usr/sbin/system_profiler SPHardwareDataType | grep "Hardware UUID" | cut -c22-57)
  #Enable location services and enforce ownership
  /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd."$uuid" LocationServicesEnabled -int 1
  /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.notbackedup."$uuid" LocationServicesEnabled -int 1
  /usr/sbin/chown -R _locationd:_locationd /var/db/locationd

  #Update Time Zone preference to auto-adjust based upon location
  /usr/bin/defaults write /Library/Preferences/com.apple.timezone.auto Active 1
  /usr/bin/defaults write /Library/Preferences/com.apple.locationmenu ShowSystemServices 1

elif [[ $OS_Version == 10.12* ]]; then
  #Enable location services and enforce ownership; path is no longer UUID dependent in Sierra
  /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -int 1
  /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.notbackedup. LocationServicesEnabled -int 1
  /usr/sbin/chown -R _locationd:_locationd /var/db/locationd

  #Update Time Zone preference to auto-adjust based upon location
  /usr/bin/defaults write /Library/Preferences/com.apple.timezone.auto Active -bool YES
  /usr/bin/defaults write /Library/Preferences/com.apple.locationmenu ShowSystemServices -bool YES

else
  echo "not running macOS 10.11 or 10.12"
fi

#Wi-Fi must be powered on to determine current location
/usr/sbin/networksetup -setairportpower $WiFiDI on

#Pause to enable location services to load properly
sleep 3

#Re-enable network time
/usr/sbin/systemsetup -setusingnetworktime on

#Python code snippet to reload AutoTimeZoneDaemon
/usr/bin/python << EOF
from Foundation import NSBundle
TZPP = NSBundle.bundleWithPath_("/System/Library/PreferencePanes/DateAndTime.prefPane/Contents/Resources/TimeZone.prefPane")
TimeZonePref          = TZPP.classNamed_('TimeZonePref')
ATZAdminPrefererences = TZPP.classNamed_('ATZAdminPrefererences')

atzap  = ATZAdminPrefererences.defaultPreferences()
pref   = TimeZonePref.alloc().init()
atzap.addObserver_forKeyPath_options_context_(pref, "enabled", 0, 0)
result = pref._startAutoTimeZoneDaemon_(0x1)
EOF

sleep 1

#Get the time from time server
/usr/sbin/systemsetup -getnetworktimeserver

#Detect the newly set timezone
/usr/sbin/systemsetup -gettimezone

exit 0

Forum|alt.badge.img+9
  • Contributor
  • 57 replies
  • July 7, 2017

Wow. That totally worked for me. The only interesting this that I found is that it said that the timezone was set to NY but then it updated the time and changed the timezone to LA which is correct since I'm sitting with this machine in Seattle. I copied and pasted your script with

sudo ./test.sh 
Password:
Network Time is already on.
Network Time Server: time.apple.com
Time Zone: America/New_York

Why does it say that it's America/New_York when it then updates to America/Los_Angeles? It's not a huge deal since it's showing the correct time but just a curious thing....


Forum|alt.badge.img+14
  • Contributor
  • 74 replies
  • July 7, 2017

Hmm, try increasing the sleep time from 1 to a higher number (maybe sleep 5) toward the bottom of the script and then run again. The /usr/sbin/systemsetup -gettimezone command that detects the set timezone might jump the gun and run before the python script has had time to fully work its magic.

I use that as a check to make sure the proper timezone was set (since error codes aren't always the most forthcoming), but you don't need it for anything aside from verification.


Forum|alt.badge.img+9
  • Contributor
  • 57 replies
  • July 7, 2017

Yup. That seems to have done the trick. I also added to the script just to echo the date/time before running the script and the date/time as the last step so you can look back historically in the policy log or the machine policy log to confirm that the date/time is actually getting updated.

## Tell the time prior to the script running
echo "The current time is `date`"
## Tell the new time after everything has been updated
echo "The new, correct time is now set as `date`"

Thanks for this Noah and everyone. This is great!


Forum|alt.badge.img+10
  • Valued Contributor
  • 182 replies
  • November 28, 2017

Just wanted to chime in and say I added an OR condition onto the 10.12 one for 10.13 and it still works great in High Sierra.

elif [[ $OS_Version == 10.12* ]] || [[ $OS_Version == 10.13* ]]; then

Thanks, @NoahRJ.


Forum|alt.badge.img+7
  • Contributor
  • 41 replies
  • November 30, 2017

So are you using this as a Self Service policy? Or automatically pushed?


Forum|alt.badge.img+10
  • Valued Contributor
  • 182 replies
  • December 1, 2017

We’re using it in a deployment policy. For new/re-imaged/DEP’d machines. Seems to work fine just firing it at computers with Remote as well, so should be good in a mass Recurring Check-In-type policy, too. Test a bit, obviously.


Forum|alt.badge.img+1
  • New Contributor
  • 2 replies
  • May 29, 2018

Anyone having success on 10.13.4? Getting errors with the python script

AttributeError: 'TimeZonePref' object has no attribute '_startAutoTimeZoneDaemon_'

Thank you all for your contributions, this thread has been hugely helpful.


Forum|alt.badge.img+10
  • Valued Contributor
  • 182 replies
  • May 30, 2018

Hadn't run the script on a 10.13.4 machine yet, but just tested, and yeah, I'm getting the same.

I'll be able to look into it later this week, but can't say I'm very familiar with Python, so someone else may prove more helpful.


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings