title: Setting system time with gps timestamp_t structure in Linux
body: <p>Setting system time with gps timestamp_t structure in Linux</p>
  
  <p>Hi Everyone,</p>
  
  <p>I'm trying to write code that as soon as I get a succesfull GPS lock (Adafruit Ultimate GPS w/ GPSD) I set the system time.  Right now, I can see that 'timestamp_t':</p>
  
  <pre><code>typedef double timestamp_t; /* Unix time in seconds with fractional part */
  </code></pre>
  
  <p>is a part of my "gps_data_t*" structure.  This is a good start, however, the function I planned on using to set the system time in Linux is:</p>
  
  <pre><code>int settimeofday(const struct timeval *tv, const struct timezone *tz);
  </code></pre>
  
  <p>I've found information on how to convert time_t to *timeval, but how should I handle this double to convert it to *timeval?</p>
  
  <p>Code:</p>
  
  <pre><code>gpsmm gps_rec("localhost", DEFAULT_GPSD_PORT);
  
  if (gps_rec.stream(WATCH_ENABLE|WATCH_JSON) == NULL) {
      std::cout &lt;&lt; "No GPSD running. exiting GPS thread." &lt;&lt; std::endl;
      return;
  }
  
  //Data structure
  struct gps_data_t* newdata;
  
  //Loop until first GPS lock to set system time
  while ((newdata = gps_rec.read()) == NULL) {
      //Wait for a valid read
  }
  
  //Set system time - timestamp_t vs timeval?
  timeval *tv{?? newdata-&gt;time ??};
  timezone *tz{ timezone(300, DST_USA)};
  settimeofday(tv, tz);
  </code></pre>
  
  <hr>
  
  <p>Some comments and links have helped me.  The confusion is differentiating between timeval, time_t, and timestamp_t.  As I understand it here are the differences, please correct if not the case:</p>
  
  <p>All are time in seconds after Jan 1st, 1970, but...</p>
  
  <p>timeval is a structure of (2) long values, tv_sec is seconds after 1/1/1970, tv_usec is microseconds after that.</p>
  
  <p>time_t is a long? that is also seconds after 1/1/1970</p>
  
  <p>timestamp_t is a double that is seconds after 1/1/1970, so the decimal part could calculate the microseconds to get 'roughly' the same precision of timeval.</p>
  
  <p>So conversion between all of them could go as such:</p>
  
  <pre><code>timeval time;
  time_t timet;
  timestamp_t timestampt;
  
  timet = time.tv_sec;   //usec dropped
  timet = timestampt;    //usec dropped
  timestampt = timet;    //usec not given
  timestampt = time.tv_sec;
  timestampt += (time.tv_usec / 1000000)  //Denominator may be off by a few 0's
  </code></pre>
  
  <p>Is this painting a clearer picture?</p>
  
  <hr>
  
  <p>To go the opposite way, which is what is needed for my application:</p>
  
  <pre><code>//Convert gps_data_t* member 'time' to timeval
  timeval tv;
  double wholeseconds, decimalseconds;
  decimalseconds = modf(newdata-&gt;time, &amp;wholeseconds);
  tv.sec = static_cast&lt;int32_t&gt;(wholeseconds);
  tv.usec = static_cast&lt;int32_t&gt;(decimalseconds * 1000000.0);
  
  //Create timezone
  timezone tz{ timezone(300, DST_USA)};
  
  //Set system time
  settimeofday(&amp;tv, &amp;tz);
  </code></pre>