4

Possible Solution

date --set="2011-12-07 01:20:15.962"  && date --rfc-3339=ns

Original Question

I can get the date with milliseconds like so:

date +"%S.%N"
date --rfc-3339=ns

According to man date I would expect to be able to set it like so:

date --set=%s.%N +`date +"%S.%N"`
date --set="%s.%N" "+1323217126.085882000"

According to my googling I would expect to be able to set the date like so (the inverse of the above):

date +%s.%N -s `date +"%S.%N"`
date +"%s.%N" -s "1323217126.085882000"

Neither work. Can someone clue me in on the issue?

P.S. No, I don't need nanosecond resolution. Yes, I know bash execution takes milliseconds. What I really need is sub-second resolution, 10ths of a second would be good enough.

2
  • 3
    Why are you manually setting the time and not using something like ntp?
    – Zoredache
    Dec 7, 2011 at 0:47
  • 2
    You're Doing It Wrong™
    – Chris S
    Dec 7, 2011 at 3:41

3 Answers 3

4

Here is a solution (Linux, NOT Unix):

date --set="2011-12-07 01:20:15.962"  && date --rfc-3339=ns

Note the delay:

CURTIME=`date --rfc-3339=ns`
date --set="${CURTIME}"    
NEWTIME=`date --rfc-3339=ns`
echo ${CURTIME}
echo ${NEWTIME}

2011-12-07 01:48:54.687216122+00:00
2011-12-07 01:48:54.720541318+00:00

As you'll notice, whole milliseconds of delay are introduced. This is due to the time it takes to initialize memory for and load the date binary. This is true for all shells and the exec of insert-higher-level-language-here

However, if you just need sub-second resolution in the range of 10ths of a second, this will good enough in many cases.

1
  • And if you're (like me) toying around and feel CURTIME is outdated too much use hwclock -s to update sys time from hardware time (and don't use hwclock -w which will set hardware clock to sys time) ^^
    – nuala
    Aug 8, 2014 at 9:59
2

If your goal is to set time in with sub-second intervals, then date seems like the wrong command if I am reading the source correctly.

Assuming you are using the coreutils version of date, then it appears to me that when.tv_nsec = 0 line is setting nanosecond portion of the when variable which is a timespec structure to zero. Even if you could convince date to accept a more accurate value, it looks to me like it would be pointless.

  # time.h
  struct timespec
  {
    __time_t tv_sec;        /* Seconds.  */
    long int tv_nsec;       /* Nanoseconds.  */
  };

  # date.c

  struct timespec when;

  # ...

              valid_date = posixtime (&when.tv_sec,
                                      datestr,
                                      (PDS_TRAILING_YEAR
                                       | PDS_CENTURY | PDS_SECONDS));
              when.tv_nsec = 0; /* FIXME: posixtime should set this.  */
  # ...

          /* Set the system clock to the specified date, then regardless of
             the success of that operation, format and print that date.  */
          if (settime (&when) != 0)
            {
              error (0, errno, _("cannot set date"));
              ok = false;
            }
1
  • The version that ships with Ubuntu seems to work. See my updated post and solution.
    – coolaj86
    Dec 7, 2011 at 1:53
1

There is a better method that doesn't require converting the timestamp to a human-readable date format as in the accepted answer. You were extremely close with your original suggestion:

date +"%s.%N" -s "1323217126.085882000"

When giving timestamps, you need to prefix with an '@' like so and not quote them:

date +"%s.%N" -s @1323217126.085882000

This will now correctly set the current Linux time in seconds with millisecond accuracy.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .