Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-6229

"std::chrono" components should be used to operate on time

    XMLWordPrintable

    Details

    • Default Severity:
      Major
    • Impact:
      Low
    • Likelihood:
      High
    • Default Quality Profiles:
      Sonar way
    • Targeted languages:
      C++
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      10min
    • Analysis Level:
      Semantic Analysis
    • Analysis Scope:
      Main Sources, Test Sources

      Description

      The chrono library, introduced in C++20, provides support for calendars, time zones, and i/o formatting and parsing operations on time-related objects.

      chrono is a better alternative to the C/POSIX functions that operate on time_t, tm, or timespec types. In comparison to C facilities, it provides a better integration with other components of the C++ standard library: (iostreams and format). Also, it supports compile-time computation and it is thread safe.

      This rule raises an issue on any use of C/POSIX functions that can be replaced with one of the std::chrono components:

      • querying for current time (time, get_timespec, clock_gettime)
      • date to time-point conversion (mktime, gmtime, localtime)
      • time serialization (ctime, asctime, strftime)
      • time parsing (strptime)

      Noncompliant Solution

      int currentMonth() {
          std::time_t tp;
          std::time(&tp);
          std::tm* date = std::gmtime(&tp);
          return date.tm_mon + 1;
      }
      
      std::chrono::system_clock::time_point makeSomeDay() {
         // Creates time_point corresponding to 2001-04-10
         std::tm date{};
         date.tm_year = 101;
         date.tm_mon = 3;
         date.tm_mday = 10;
         std::time_t t = std::mktime(&date); // Noncomplaint
         return std::chrono::system_clock::from_time_t(t);
      }
      
      std::optional<int> yearOfTimePoint(std::chrono::system_clock::time_point tp) {
         std::time_t  t = std::chrono::system_clock::to_time_t(tp);
         std::tm* date = std::gmtime(&t); // Noncomplaint
         if (!date)
            return std::nullopt;
         return date->tm_year + 1900;
      }
      
      std::string toIsoString(std::chrono::system_clock::time_point tp) {
         std::time_t  t = std::chrono::system_clock::to_time_t(tp);
         std::tm* date = std::gmtime(&t);  // Noncomplaint
         if (!date)
            throw InvalidDate();
      
         std::string buffer(100);
         std::size_t written = std::strftime(buffer.data(), buffer.size(), "%F", date);
         buffer.resize(written);
         return buffer;
      }
      

      Compliant Solution

      std::chrono::month currentMonth() {
         using namespace std::chrono;
         auto dp = floor<days>(system_clock::now());
         return year_month_day(dp).month();
      }
      
      std::chrono::system_clock::time_point makeSomeDay() {
         using namespace std::chrono;
         retrun sys_days(2001y/April/10);
      }
      
      std::optional<int> yearOfTimePoint(std::chrono::system_clock::time_point tp) {
         using namespace std::chrono;
         year_month_day date(floor<days>(tp));
         if (!date.ok())
           return std::nullopt;
         return date.year();
      }
      
      std::string toIsoString(std::chrono::system_clock::time_point tp) {
         return std::format("{:%F}", tp);
      }
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              tomasz.kaminski Tomasz KamiƄski
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated: