Convert a date string for date or systemsetup command

applescriptbashcommand lineterminaltime

I have a date in this format: 12 May 2017 09:04:26

I want to auto-update the time of my Mac from this string with a command line.

The first way I found is to use date command line, as explained in Apple's date manpage, the accepted format is [[[mm]dd]HH]MM[[cc]yy][.ss] (or {month}{day}{hours}{minutes}{century}{year}.{seconds}).

The second way I found is to use systemsetup command, with setdate or settime flags. Accepted formats are: mm:dd:yy (or {month}:{day}:{year}) for setdate and hh:mm:ss (or {hour}:{minutes}:{seconds}) for settime.

First question: what is the best solution to update time?

And how can I convert (with AppleScript or Bash Script or other method) the first string to a valid format for date or systemsetup?

The date manpage talking about strptime command but I don't know how can I use it.


Update (after @klanomath answer)

Here is the script I'm using to update my system time when it's wrong (in my case sometimes date go back to 2013). Script is checking some ntp servers with ntpdate and sntp commands and if not works, trying to get the date of google.com http header to set it with date and systemsetup commands.

#!/bin/bash

# Uncomment for debug
#set -x

# Check if bad year
is_2013() {
 YEAR=$(sudo /usr/sbin/systemsetup -getdate | cut -d '/' -f 3)
 if [ $YEAR == "2013" ]; then return 0; else return 1; fi
}

http_date_ud() {
 # First method, update system time with "date" command 
 sudo date -f "%a, %d %b %Y %H:%M:%S %Z" "$1"

 # Second method, update system time with "systemsetup" command
 if is_2013 $1; then
  NDATE=$(date -j -f "%a, %d %b %Y %H:%M:%S %Z" "$1" "+%m:%d:%y")
  printf "$NDATE"
  NTIME=$(echo "$1" | cut -d' ' -f5)
  printf "$NTIME"
  sudo /usr/sbin/systemsetup -setusingnetworktime off
  sudo /usr/sbin/systemsetup -setdate $NDATE
  sudo /usr/sbin/systemsetup -settime $NTIME
  sudo /usr/sbin/systemsetup -setusingnetworktime on
 fi
}

# 1°/ Trying with ntpdate on Apple + NTP global time servers
if is_2013 $1; then ntpdate -t 4 -u time.apple.com; else exit 0; fi
if is_2013 $1; then ntpdate -t 4 -u pool.ntp.org; else exit 0; fi

# 2°/ Trying with sntp with Apple + NTP local time servers
if is_2013 $1; then sntp -s time.euro.apple.com; else exit 0; fi
if is_2013 $1; then sntp -s fr.pool.ntp.org; else exit 0; fi

# 3°/ Trying with HTTP header
HTTP_DATE=$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f4-9)
lc_tmp=$LC_ALL && LC_ALL=C
http_date_ud "$HTTP_DATE"
LC_ALL=lc_tmp

Best Answer

To properly set a more or less current system date and time with date and wget use:

sudo date -f "%d %b %Y %H:%M:%S %Z" "$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-9)"

Using ... cut -d' ' -f5-8)" (see your comment) will omit the time zone and you would have to add 1 or 2 hours depending on the state of the day light saving time to adjust your local time.

The result of wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-9 is something like 12 May 2017 12:17:00 GMT.

So the date/time format of the date command to set date/time has to be %d %b %Y %H:%M:%S %Z. Since May is the short as well as the long name of the month and we don't really know the format of the month's name in Google's reply, %b may have to be replaced by %B in June :-).


Due to retention and other deficiencies this is not very accurate and the ∂ is up to 3.5 seconds (usually 0.32 seconds here) compared to the time received via ntp.

To get rid of the sntp error mentioned in your comment, do the following:

sudo touch /var/db/ntp-kod
sudo chmod 666 /var/db/ntp-kod

Now sntp fr.pool.ntp.org and sudo sntp -s fr.pool.ntp.org should work.