Esempio n. 1
0
/** Sets the date and time using an ISO8601-formatted string
 *
 * @param str :: ISO8601 format string: "yyyy-mm-ddThh:mm:ss[Z+-]tz:tz"
 */
void DateAndTime::set_from_ISO8601_string(const std::string str)
{
  //Make a copy
  std::string time = str;

  //Default of no timezone offset
  bool positive_offset = true;
  time_duration tz_offset = boost::posix_time::seconds(0);

  //Replace "T" with a space
  size_t n = time.find('T');
  if (n != std::string::npos)
  {
    //Take out the T, for later
    time[n] = ' ';

    //Adjust for time zones. Fun!
    //Look for the time zone marker
    size_t n2;
    n2 = time.find('Z', n);
    if (n2 != std::string::npos)
    {
      //Found a Z. Remove it, and no timezone fix
      time = time.substr(0, n2);
    }
    else
    {
      //Look for a + or - indicating time zone offset
      size_t n_plus,n_minus,n5;
      n_plus = time.find('+', n);
      n_minus = time.find('-', n);
      if ((n_plus != std::string::npos) || (n_minus != std::string::npos))
      {
        //Either a - or a + was found
        if (n_plus != std::string::npos)
        {
          positive_offset = true;
          n5 = n_plus;
        }
        else
        {
          positive_offset = false;
          n5 = n_minus;
        }

        //Now, parse the offset time
        std::string offset_str = time.substr(n5+1, time.size()-n5-1);

        //Take out the offset from time string
        time = time.substr(0, n5);

        //Separate into minutes and hours
        size_t n6;
        std::string hours_str("0"), minutes_str("0");
        n6 = offset_str.find(':');
        if ((n6 != std::string::npos))
        {
          //Yes, minutes offset are specified
          minutes_str = offset_str.substr(n6+1, offset_str.size()-n6-1);
          hours_str = offset_str.substr(0, n6);
        }
        else
          //Just hours
          hours_str = offset_str;

        //Convert to a time_duration
        tz_offset = boost::posix_time::hours( boost::lexical_cast<long>(hours_str)) +
            boost::posix_time::minutes( boost::lexical_cast<long>(minutes_str));

      }
    }

  }


  //The boost conversion will convert the string, then we subtract the time zone offset
  if (positive_offset)
    //The timezone is + so we need to subtract the hours
    this->set_from_ptime( boost::posix_time::time_from_string(time) - tz_offset );
  else
    //The timezone is - so we need to ADD the hours
    this->set_from_ptime( boost::posix_time::time_from_string(time) + tz_offset );
}
Esempio n. 2
0
/** Sets the date and time using an ISO8601-formatted string
 *
 * @param str :: ISO8601 format string: "yyyy-mm-ddThh:mm:ss[Z+-]tz:tz"
 * @param displayLogs :: flag to indiciate if the logs should be displayed
 */
void DateAndTime::setFromISO8601(const std::string &str, bool displayLogs) {
  // Make a copy
  std::string time = str;
  // Some ARGUS files have an invalid date with a space instead of zero.
  // To enable such files to be loaded we correct the date and issue a warning
  // (ticket #4017).
  std::string date = time.substr(
      0, 10); // just take the date not the time or any date-time separator
  const size_t nSpace = date.find(' ');
  if (nSpace != std::string::npos) {
    if (displayLogs) {
      g_log.warning() << "Invalid ISO8601 date " << time;
    }
    time[nSpace] = '0'; // replace space with 0

    // Do again in case of second space
    date[nSpace] = '0';
    const size_t nSecondSpace = date.find(' ');
    if (nSecondSpace != std::string::npos)
      time[nSecondSpace] = '0';
    if (displayLogs) {
      g_log.warning() << " corrected to " << time << '\n';
    }
  }

  // Default of no timezone offset
  bool positive_offset = true;
  time_duration tz_offset = boost::posix_time::seconds(0);

  // Replace "T" with a space
  const size_t nCharT = time.find('T');
  if (nCharT != std::string::npos) {
    // Take out the T, for later
    time[nCharT] = ' ';

    // Adjust for time zones. Fun!
    // Look for the time zone marker
    const size_t nCharZ = time.find('Z', nCharT);
    if (nCharZ != std::string::npos) {
      // Found a Z. Remove it, and no timezone fix
      time = time.substr(0, nCharZ);
    } else {
      // Look for a + or - indicating time zone offset
      size_t n_plus, n_minus;
      n_plus = time.find('+', nCharT);
      n_minus = time.find('-', nCharT);
      if ((n_plus != std::string::npos) || (n_minus != std::string::npos)) {
        size_t nPlusMinus;
        // Either a - or a + was found
        if (n_plus != std::string::npos) {
          positive_offset = true;
          nPlusMinus = n_plus;
        } else {
          positive_offset = false;
          nPlusMinus = n_minus;
        }

        // Now, parse the offset time
        std::string offset_str =
            time.substr(nPlusMinus + 1, time.size() - nPlusMinus - 1);

        // Take out the offset from time string
        time = time.substr(0, nPlusMinus);

        // Separate into minutes and hours
        std::string hours_str("0"), minutes_str("0");
        const size_t nColon = offset_str.find(':');
        if ((nColon != std::string::npos)) {
          // Yes, minutes offset are specified
          minutes_str =
              offset_str.substr(nColon + 1, offset_str.size() - nColon - 1);
          hours_str = offset_str.substr(0, nColon);
        } else
          // Just hours
          hours_str = offset_str;

        // Convert to a time_duration
        tz_offset =
            boost::posix_time::hours(boost::lexical_cast<long>(hours_str)) +
            boost::posix_time::minutes(boost::lexical_cast<long>(minutes_str));
      }
    }
  }

  // The boost conversion will convert the string, then we subtract the time
  // zone offset
  // Different versions of boost accept slightly different things. Earlier
  // versions
  // seem to accept only a date as valid, whereas later versions do not. We want
  // the
  // string to always denote the full timestamp so we check for a colon and if
  // it is not present then throw an exception.
  if (time.find(':') == std::string::npos)
    throw std::invalid_argument("Error interpreting string '" + str +
                                "' as a date/time.");
  try {
    if (positive_offset)
      // The timezone is + so we need to subtract the hours
      this->set_from_ptime(boost::posix_time::time_from_string(time) -
                           tz_offset);
    else
      // The timezone is - so we need to ADD the hours
      this->set_from_ptime(boost::posix_time::time_from_string(time) +
                           tz_offset);
  } catch (std::exception &) {
    // Re-throw a more helpful error message
    throw std::invalid_argument("Error interpreting string '" + str +
                                "' as a date/time.");
  }
}