Timestamp function with millisecond precision












4














I want to be able to print timestamps with milliseconds precision and time_t doesn't provide this. I also want the code to be portable, so operating specific functions are out. ftime seems to be deprecated but there doesn't seem to be a general-purpose alternative to using ftime.



How could this be improved?



#include <stdio.h>
#include <string.h>
#include <systimeb.h>
#include <time.h>

static char* get_timestamp(char* buf) {
struct timeb start;
char append[100];
if (buf) {
ftime(&start);
strftime(buf, 100, "%H:%M:%S", localtime(&start.time));

/* append milliseconds */
sprintf(append, ":%03u", start.millitm);
strcat(buf, append);
}
return buf;
}

int main()
{
char tmp[100];
int countdown = 0;
for (int i = 0; i < 10; i++, countdown = 0) {
printf("%sn", get_timestamp(tmp));
while (countdown++ < 1000000)
;
}
}









share|improve this question





























    4














    I want to be able to print timestamps with milliseconds precision and time_t doesn't provide this. I also want the code to be portable, so operating specific functions are out. ftime seems to be deprecated but there doesn't seem to be a general-purpose alternative to using ftime.



    How could this be improved?



    #include <stdio.h>
    #include <string.h>
    #include <systimeb.h>
    #include <time.h>

    static char* get_timestamp(char* buf) {
    struct timeb start;
    char append[100];
    if (buf) {
    ftime(&start);
    strftime(buf, 100, "%H:%M:%S", localtime(&start.time));

    /* append milliseconds */
    sprintf(append, ":%03u", start.millitm);
    strcat(buf, append);
    }
    return buf;
    }

    int main()
    {
    char tmp[100];
    int countdown = 0;
    for (int i = 0; i < 10; i++, countdown = 0) {
    printf("%sn", get_timestamp(tmp));
    while (countdown++ < 1000000)
    ;
    }
    }









    share|improve this question



























      4












      4








      4







      I want to be able to print timestamps with milliseconds precision and time_t doesn't provide this. I also want the code to be portable, so operating specific functions are out. ftime seems to be deprecated but there doesn't seem to be a general-purpose alternative to using ftime.



      How could this be improved?



      #include <stdio.h>
      #include <string.h>
      #include <systimeb.h>
      #include <time.h>

      static char* get_timestamp(char* buf) {
      struct timeb start;
      char append[100];
      if (buf) {
      ftime(&start);
      strftime(buf, 100, "%H:%M:%S", localtime(&start.time));

      /* append milliseconds */
      sprintf(append, ":%03u", start.millitm);
      strcat(buf, append);
      }
      return buf;
      }

      int main()
      {
      char tmp[100];
      int countdown = 0;
      for (int i = 0; i < 10; i++, countdown = 0) {
      printf("%sn", get_timestamp(tmp));
      while (countdown++ < 1000000)
      ;
      }
      }









      share|improve this question















      I want to be able to print timestamps with milliseconds precision and time_t doesn't provide this. I also want the code to be portable, so operating specific functions are out. ftime seems to be deprecated but there doesn't seem to be a general-purpose alternative to using ftime.



      How could this be improved?



      #include <stdio.h>
      #include <string.h>
      #include <systimeb.h>
      #include <time.h>

      static char* get_timestamp(char* buf) {
      struct timeb start;
      char append[100];
      if (buf) {
      ftime(&start);
      strftime(buf, 100, "%H:%M:%S", localtime(&start.time));

      /* append milliseconds */
      sprintf(append, ":%03u", start.millitm);
      strcat(buf, append);
      }
      return buf;
      }

      int main()
      {
      char tmp[100];
      int countdown = 0;
      for (int i = 0; i < 10; i++, countdown = 0) {
      printf("%sn", get_timestamp(tmp));
      while (countdown++ < 1000000)
      ;
      }
      }






      c datetime formatting portability






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 20 '16 at 16:56









      200_success

      128k15150412




      128k15150412










      asked Feb 20 '16 at 15:42









      arcomber

      89821527




      89821527






















          2 Answers
          2






          active

          oldest

          votes


















          5














          You state that operating specific functions are out, which I assume means that you don't want to use operating system specific system functions. However in this particular case that is actually hindering you from actually solving your task, as POSIX-based systems and Windows-based systems has two different ways of handling this.



          Although the ftime is present in various operating system, it has been marked as obsolete as of POSIX.1-2008:




          4.2BSD, POSIX.1-2001. POSIX.1-2008 removes the specification of ftime().



          This function is obsolete. Don't use it. If the time in seconds
          suffices, time(2) can be used; gettimeofday(2) gives microseconds;
          clock_gettime(2) gives nanoseconds but is not as widely available.




          Further is the gettimeofday() also obsolete as of POSIX.1-2008, leaving only the clock_gettime() alternative, which is not as widely available. Most notably not present in Windows, as indicated in "Porting clock_gettime to windows".



          On Windows there are some other options, but seems that most fall back to using QueryPerformanceCounter & co (referred to as QPCs) as indicated in "Acquiring high-resolution time stamps". Some of my search findings also indicate that the QPCs are not be trusted in SMP (Symmetric MultiProcessing environments).



          In other words, if you want to do this correctly for use in various operating systems, you do need to make it operating system dependent. If you choose to carry on with your solution using the obsolete ftime() more could surely be said, but here are some comments on your actual code:





          • Loose the append variable – You already have room in buf for the result, and know how much you've already used. I.e. replace it with something like either sprintf(&buf[8], ":%03u", start.millitm); or sprintf(buf + 8, ":%03u", start.millitm);1, and you can return without doing the strcat at the end.


          • Avoid busy loops – Your while loop is called a busy loop as it does nothing excepting counting. It is usually better to trigger a sleep function or similar, allowing the processor to do other work in between.


          • Strange reset of countdown – Instead of resetting the countdown in the for loop, it would be clearer code to reset it just before the while loop, or even better (if persisting to use the busy loop) to make it into a locally scoped for loop, i.e for (int countdown = 0; countdown < 1000000; countdown++) ;


          • Decide on one style of bracing – Decide whether you want to have opening braces on the start of the line, or end of preceding line, and stick to it. Mixing like you've done here make your code somewhat harder to read, and when mixing with empty block (aka the busy loop) with missing braces, it is not good.



            Some guys advocate a different opening brace style for functions versus other blocks, but I would suggest using the same style for everything making it more consistent.




          Addendum: C11 and xtime_get or rather timespec_get



          Jerry Coffin refers to a xtime_get() with potential nanoseconds precision (albeit still dependent on operating system precision). This is part of the C++ boost library. It was proposed to be included in C11 (see N1548.pdf, 7.25.7, p 383. This was revised in N1570, 7.27.2.7, into a timespec_get() function. N1570 is the latest draft available, before the standard was defined (and made commercially available). From this I quote:




          3 If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock.321)

          ...
          321) Although a struct timespec object describes times with nanosecond resolution, the available resolution is system dependent and may even be greater than 1 second.




          This does however seem to have made it into C11 (also known as ISO/IEC 9899:2011), according to the table of contents listed here, see section 7.27.2.5. So if your compiler and libraries is compliant to C112, you might use timespec_get() and possibly get a system dependent precision up to nanoseconds (or even greater than 1 second).





          1 Thanks to 200_success for pointing out error in code related to buf[8] not being an acceptable target for sprintf()
          2 For the gcc family this seems to be gcc ver 4.6 and glibc ver 2.16, or newer






          share|improve this answer































            0














            I answered a similar question on Stack Overflow. I wanted a timestamp in a specific format, that could be obtained from a function repeatedly.



            My implementation is different than the original posters, for very specific reasons. The goal is thus to create a simple timestamp structure and a function that can create it repeatedly without arguments. I think the function below does that.



            A timestamp function should return a timestamp. It should not require the user to have know the necessary length of the char*. Such details should be hidden from the user. If not the user must manage the char* or keep tabs on how users of this function pass char* variables to it.



            The function clock_gettime is the ideal POSIX function, but it is not universally supported. Avoid the other deprecated functions such as gettimeofday. As someone said earlier, ftime is not the function to use, and neither is gettimeofday.



            I think the code below is mostly portable. I think the trick with timestamp functions is not so much portability, but avoiding the unnecessary usage of dynamically allocated memory. I think this is important because for embedded environments several rules preclude the usage of such C constructs.



            Also, strcat requires an implicit search for ''. For the original solution strcat should cause no problems, but I generally avoid the use of strcat because of it's own problems.



            My function returns a timestamp with a timestring (not ambiguous) and not a char* (ambiguous) - essentially this timestamp function is at a suitable code 'level', the reader knows what he is being presented with. I am not inter-mixing low and medium level code. I have a medium level type (timestamp) and a medium level function (getTimestamp) and it requires no arguments.



            It would be 'nice' if clock_gettime had macro options for something like RAW_GPS_TIME, J2000_TAI_TIME, J2000_UTC_TIME and so forth, providing that such time sources were available, but this is another discussion.



            struct Timestamp {
            time_t seconds;
            long milliseconds;
            char timestring[32];
            };


            struct Timestamp getTimestamp()
            {
            char timebuffer[32] = {0};
            struct timeval tv = {0};
            struct tm *tmval = NULL;
            struct tm gmtval = {0};
            struct timespec curtime = {0};

            struct Timestamp timestamp;

            int i = 0;

            // Get current time
            clock_gettime(CLOCK_REALTIME, &curtime);


            // Set the fields
            timestamp.seconds = curtime.tv_sec;
            timestamp.milliseconds = round(curtime.tv_nsec/1.0e6);

            if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL)
            {
            // Build the first part of the time
            strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval);

            // Add the milliseconds part and build the time string
            snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds);
            }

            return timestamp;
            }

            int main()
            {
            int i = 0;
            struct timespec sleeptime = {0, 5000000L};

            struct Timestamp timestamp;

            for (i=0; i < 20; i++)
            {
            timestamp = getTimestamp();
            printf("Time is: %s n", timestamp.timestring);
            nanosleep(&sleeptime, NULL);
            }

            return 0;
            }





            share|improve this answer























              Your Answer





              StackExchange.ifUsing("editor", function () {
              return StackExchange.using("mathjaxEditing", function () {
              StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
              StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
              });
              });
              }, "mathjax-editing");

              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "196"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f120628%2ftimestamp-function-with-millisecond-precision%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              5














              You state that operating specific functions are out, which I assume means that you don't want to use operating system specific system functions. However in this particular case that is actually hindering you from actually solving your task, as POSIX-based systems and Windows-based systems has two different ways of handling this.



              Although the ftime is present in various operating system, it has been marked as obsolete as of POSIX.1-2008:




              4.2BSD, POSIX.1-2001. POSIX.1-2008 removes the specification of ftime().



              This function is obsolete. Don't use it. If the time in seconds
              suffices, time(2) can be used; gettimeofday(2) gives microseconds;
              clock_gettime(2) gives nanoseconds but is not as widely available.




              Further is the gettimeofday() also obsolete as of POSIX.1-2008, leaving only the clock_gettime() alternative, which is not as widely available. Most notably not present in Windows, as indicated in "Porting clock_gettime to windows".



              On Windows there are some other options, but seems that most fall back to using QueryPerformanceCounter & co (referred to as QPCs) as indicated in "Acquiring high-resolution time stamps". Some of my search findings also indicate that the QPCs are not be trusted in SMP (Symmetric MultiProcessing environments).



              In other words, if you want to do this correctly for use in various operating systems, you do need to make it operating system dependent. If you choose to carry on with your solution using the obsolete ftime() more could surely be said, but here are some comments on your actual code:





              • Loose the append variable – You already have room in buf for the result, and know how much you've already used. I.e. replace it with something like either sprintf(&buf[8], ":%03u", start.millitm); or sprintf(buf + 8, ":%03u", start.millitm);1, and you can return without doing the strcat at the end.


              • Avoid busy loops – Your while loop is called a busy loop as it does nothing excepting counting. It is usually better to trigger a sleep function or similar, allowing the processor to do other work in between.


              • Strange reset of countdown – Instead of resetting the countdown in the for loop, it would be clearer code to reset it just before the while loop, or even better (if persisting to use the busy loop) to make it into a locally scoped for loop, i.e for (int countdown = 0; countdown < 1000000; countdown++) ;


              • Decide on one style of bracing – Decide whether you want to have opening braces on the start of the line, or end of preceding line, and stick to it. Mixing like you've done here make your code somewhat harder to read, and when mixing with empty block (aka the busy loop) with missing braces, it is not good.



                Some guys advocate a different opening brace style for functions versus other blocks, but I would suggest using the same style for everything making it more consistent.




              Addendum: C11 and xtime_get or rather timespec_get



              Jerry Coffin refers to a xtime_get() with potential nanoseconds precision (albeit still dependent on operating system precision). This is part of the C++ boost library. It was proposed to be included in C11 (see N1548.pdf, 7.25.7, p 383. This was revised in N1570, 7.27.2.7, into a timespec_get() function. N1570 is the latest draft available, before the standard was defined (and made commercially available). From this I quote:




              3 If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock.321)

              ...
              321) Although a struct timespec object describes times with nanosecond resolution, the available resolution is system dependent and may even be greater than 1 second.




              This does however seem to have made it into C11 (also known as ISO/IEC 9899:2011), according to the table of contents listed here, see section 7.27.2.5. So if your compiler and libraries is compliant to C112, you might use timespec_get() and possibly get a system dependent precision up to nanoseconds (or even greater than 1 second).





              1 Thanks to 200_success for pointing out error in code related to buf[8] not being an acceptable target for sprintf()
              2 For the gcc family this seems to be gcc ver 4.6 and glibc ver 2.16, or newer






              share|improve this answer




























                5














                You state that operating specific functions are out, which I assume means that you don't want to use operating system specific system functions. However in this particular case that is actually hindering you from actually solving your task, as POSIX-based systems and Windows-based systems has two different ways of handling this.



                Although the ftime is present in various operating system, it has been marked as obsolete as of POSIX.1-2008:




                4.2BSD, POSIX.1-2001. POSIX.1-2008 removes the specification of ftime().



                This function is obsolete. Don't use it. If the time in seconds
                suffices, time(2) can be used; gettimeofday(2) gives microseconds;
                clock_gettime(2) gives nanoseconds but is not as widely available.




                Further is the gettimeofday() also obsolete as of POSIX.1-2008, leaving only the clock_gettime() alternative, which is not as widely available. Most notably not present in Windows, as indicated in "Porting clock_gettime to windows".



                On Windows there are some other options, but seems that most fall back to using QueryPerformanceCounter & co (referred to as QPCs) as indicated in "Acquiring high-resolution time stamps". Some of my search findings also indicate that the QPCs are not be trusted in SMP (Symmetric MultiProcessing environments).



                In other words, if you want to do this correctly for use in various operating systems, you do need to make it operating system dependent. If you choose to carry on with your solution using the obsolete ftime() more could surely be said, but here are some comments on your actual code:





                • Loose the append variable – You already have room in buf for the result, and know how much you've already used. I.e. replace it with something like either sprintf(&buf[8], ":%03u", start.millitm); or sprintf(buf + 8, ":%03u", start.millitm);1, and you can return without doing the strcat at the end.


                • Avoid busy loops – Your while loop is called a busy loop as it does nothing excepting counting. It is usually better to trigger a sleep function or similar, allowing the processor to do other work in between.


                • Strange reset of countdown – Instead of resetting the countdown in the for loop, it would be clearer code to reset it just before the while loop, or even better (if persisting to use the busy loop) to make it into a locally scoped for loop, i.e for (int countdown = 0; countdown < 1000000; countdown++) ;


                • Decide on one style of bracing – Decide whether you want to have opening braces on the start of the line, or end of preceding line, and stick to it. Mixing like you've done here make your code somewhat harder to read, and when mixing with empty block (aka the busy loop) with missing braces, it is not good.



                  Some guys advocate a different opening brace style for functions versus other blocks, but I would suggest using the same style for everything making it more consistent.




                Addendum: C11 and xtime_get or rather timespec_get



                Jerry Coffin refers to a xtime_get() with potential nanoseconds precision (albeit still dependent on operating system precision). This is part of the C++ boost library. It was proposed to be included in C11 (see N1548.pdf, 7.25.7, p 383. This was revised in N1570, 7.27.2.7, into a timespec_get() function. N1570 is the latest draft available, before the standard was defined (and made commercially available). From this I quote:




                3 If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock.321)

                ...
                321) Although a struct timespec object describes times with nanosecond resolution, the available resolution is system dependent and may even be greater than 1 second.




                This does however seem to have made it into C11 (also known as ISO/IEC 9899:2011), according to the table of contents listed here, see section 7.27.2.5. So if your compiler and libraries is compliant to C112, you might use timespec_get() and possibly get a system dependent precision up to nanoseconds (or even greater than 1 second).





                1 Thanks to 200_success for pointing out error in code related to buf[8] not being an acceptable target for sprintf()
                2 For the gcc family this seems to be gcc ver 4.6 and glibc ver 2.16, or newer






                share|improve this answer


























                  5












                  5








                  5






                  You state that operating specific functions are out, which I assume means that you don't want to use operating system specific system functions. However in this particular case that is actually hindering you from actually solving your task, as POSIX-based systems and Windows-based systems has two different ways of handling this.



                  Although the ftime is present in various operating system, it has been marked as obsolete as of POSIX.1-2008:




                  4.2BSD, POSIX.1-2001. POSIX.1-2008 removes the specification of ftime().



                  This function is obsolete. Don't use it. If the time in seconds
                  suffices, time(2) can be used; gettimeofday(2) gives microseconds;
                  clock_gettime(2) gives nanoseconds but is not as widely available.




                  Further is the gettimeofday() also obsolete as of POSIX.1-2008, leaving only the clock_gettime() alternative, which is not as widely available. Most notably not present in Windows, as indicated in "Porting clock_gettime to windows".



                  On Windows there are some other options, but seems that most fall back to using QueryPerformanceCounter & co (referred to as QPCs) as indicated in "Acquiring high-resolution time stamps". Some of my search findings also indicate that the QPCs are not be trusted in SMP (Symmetric MultiProcessing environments).



                  In other words, if you want to do this correctly for use in various operating systems, you do need to make it operating system dependent. If you choose to carry on with your solution using the obsolete ftime() more could surely be said, but here are some comments on your actual code:





                  • Loose the append variable – You already have room in buf for the result, and know how much you've already used. I.e. replace it with something like either sprintf(&buf[8], ":%03u", start.millitm); or sprintf(buf + 8, ":%03u", start.millitm);1, and you can return without doing the strcat at the end.


                  • Avoid busy loops – Your while loop is called a busy loop as it does nothing excepting counting. It is usually better to trigger a sleep function or similar, allowing the processor to do other work in between.


                  • Strange reset of countdown – Instead of resetting the countdown in the for loop, it would be clearer code to reset it just before the while loop, or even better (if persisting to use the busy loop) to make it into a locally scoped for loop, i.e for (int countdown = 0; countdown < 1000000; countdown++) ;


                  • Decide on one style of bracing – Decide whether you want to have opening braces on the start of the line, or end of preceding line, and stick to it. Mixing like you've done here make your code somewhat harder to read, and when mixing with empty block (aka the busy loop) with missing braces, it is not good.



                    Some guys advocate a different opening brace style for functions versus other blocks, but I would suggest using the same style for everything making it more consistent.




                  Addendum: C11 and xtime_get or rather timespec_get



                  Jerry Coffin refers to a xtime_get() with potential nanoseconds precision (albeit still dependent on operating system precision). This is part of the C++ boost library. It was proposed to be included in C11 (see N1548.pdf, 7.25.7, p 383. This was revised in N1570, 7.27.2.7, into a timespec_get() function. N1570 is the latest draft available, before the standard was defined (and made commercially available). From this I quote:




                  3 If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock.321)

                  ...
                  321) Although a struct timespec object describes times with nanosecond resolution, the available resolution is system dependent and may even be greater than 1 second.




                  This does however seem to have made it into C11 (also known as ISO/IEC 9899:2011), according to the table of contents listed here, see section 7.27.2.5. So if your compiler and libraries is compliant to C112, you might use timespec_get() and possibly get a system dependent precision up to nanoseconds (or even greater than 1 second).





                  1 Thanks to 200_success for pointing out error in code related to buf[8] not being an acceptable target for sprintf()
                  2 For the gcc family this seems to be gcc ver 4.6 and glibc ver 2.16, or newer






                  share|improve this answer














                  You state that operating specific functions are out, which I assume means that you don't want to use operating system specific system functions. However in this particular case that is actually hindering you from actually solving your task, as POSIX-based systems and Windows-based systems has two different ways of handling this.



                  Although the ftime is present in various operating system, it has been marked as obsolete as of POSIX.1-2008:




                  4.2BSD, POSIX.1-2001. POSIX.1-2008 removes the specification of ftime().



                  This function is obsolete. Don't use it. If the time in seconds
                  suffices, time(2) can be used; gettimeofday(2) gives microseconds;
                  clock_gettime(2) gives nanoseconds but is not as widely available.




                  Further is the gettimeofday() also obsolete as of POSIX.1-2008, leaving only the clock_gettime() alternative, which is not as widely available. Most notably not present in Windows, as indicated in "Porting clock_gettime to windows".



                  On Windows there are some other options, but seems that most fall back to using QueryPerformanceCounter & co (referred to as QPCs) as indicated in "Acquiring high-resolution time stamps". Some of my search findings also indicate that the QPCs are not be trusted in SMP (Symmetric MultiProcessing environments).



                  In other words, if you want to do this correctly for use in various operating systems, you do need to make it operating system dependent. If you choose to carry on with your solution using the obsolete ftime() more could surely be said, but here are some comments on your actual code:





                  • Loose the append variable – You already have room in buf for the result, and know how much you've already used. I.e. replace it with something like either sprintf(&buf[8], ":%03u", start.millitm); or sprintf(buf + 8, ":%03u", start.millitm);1, and you can return without doing the strcat at the end.


                  • Avoid busy loops – Your while loop is called a busy loop as it does nothing excepting counting. It is usually better to trigger a sleep function or similar, allowing the processor to do other work in between.


                  • Strange reset of countdown – Instead of resetting the countdown in the for loop, it would be clearer code to reset it just before the while loop, or even better (if persisting to use the busy loop) to make it into a locally scoped for loop, i.e for (int countdown = 0; countdown < 1000000; countdown++) ;


                  • Decide on one style of bracing – Decide whether you want to have opening braces on the start of the line, or end of preceding line, and stick to it. Mixing like you've done here make your code somewhat harder to read, and when mixing with empty block (aka the busy loop) with missing braces, it is not good.



                    Some guys advocate a different opening brace style for functions versus other blocks, but I would suggest using the same style for everything making it more consistent.




                  Addendum: C11 and xtime_get or rather timespec_get



                  Jerry Coffin refers to a xtime_get() with potential nanoseconds precision (albeit still dependent on operating system precision). This is part of the C++ boost library. It was proposed to be included in C11 (see N1548.pdf, 7.25.7, p 383. This was revised in N1570, 7.27.2.7, into a timespec_get() function. N1570 is the latest draft available, before the standard was defined (and made commercially available). From this I quote:




                  3 If base is TIME_UTC, the tv_sec member is set to the number of seconds since an implementation defined epoch, truncated to a whole value and the tv_nsec member is set to the integral number of nanoseconds, rounded to the resolution of the system clock.321)

                  ...
                  321) Although a struct timespec object describes times with nanosecond resolution, the available resolution is system dependent and may even be greater than 1 second.




                  This does however seem to have made it into C11 (also known as ISO/IEC 9899:2011), according to the table of contents listed here, see section 7.27.2.5. So if your compiler and libraries is compliant to C112, you might use timespec_get() and possibly get a system dependent precision up to nanoseconds (or even greater than 1 second).





                  1 Thanks to 200_success for pointing out error in code related to buf[8] not being an acceptable target for sprintf()
                  2 For the gcc family this seems to be gcc ver 4.6 and glibc ver 2.16, or newer







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited May 23 '17 at 12:40









                  Community

                  1




                  1










                  answered Feb 20 '16 at 16:48









                  holroy

                  10.8k11752




                  10.8k11752

























                      0














                      I answered a similar question on Stack Overflow. I wanted a timestamp in a specific format, that could be obtained from a function repeatedly.



                      My implementation is different than the original posters, for very specific reasons. The goal is thus to create a simple timestamp structure and a function that can create it repeatedly without arguments. I think the function below does that.



                      A timestamp function should return a timestamp. It should not require the user to have know the necessary length of the char*. Such details should be hidden from the user. If not the user must manage the char* or keep tabs on how users of this function pass char* variables to it.



                      The function clock_gettime is the ideal POSIX function, but it is not universally supported. Avoid the other deprecated functions such as gettimeofday. As someone said earlier, ftime is not the function to use, and neither is gettimeofday.



                      I think the code below is mostly portable. I think the trick with timestamp functions is not so much portability, but avoiding the unnecessary usage of dynamically allocated memory. I think this is important because for embedded environments several rules preclude the usage of such C constructs.



                      Also, strcat requires an implicit search for ''. For the original solution strcat should cause no problems, but I generally avoid the use of strcat because of it's own problems.



                      My function returns a timestamp with a timestring (not ambiguous) and not a char* (ambiguous) - essentially this timestamp function is at a suitable code 'level', the reader knows what he is being presented with. I am not inter-mixing low and medium level code. I have a medium level type (timestamp) and a medium level function (getTimestamp) and it requires no arguments.



                      It would be 'nice' if clock_gettime had macro options for something like RAW_GPS_TIME, J2000_TAI_TIME, J2000_UTC_TIME and so forth, providing that such time sources were available, but this is another discussion.



                      struct Timestamp {
                      time_t seconds;
                      long milliseconds;
                      char timestring[32];
                      };


                      struct Timestamp getTimestamp()
                      {
                      char timebuffer[32] = {0};
                      struct timeval tv = {0};
                      struct tm *tmval = NULL;
                      struct tm gmtval = {0};
                      struct timespec curtime = {0};

                      struct Timestamp timestamp;

                      int i = 0;

                      // Get current time
                      clock_gettime(CLOCK_REALTIME, &curtime);


                      // Set the fields
                      timestamp.seconds = curtime.tv_sec;
                      timestamp.milliseconds = round(curtime.tv_nsec/1.0e6);

                      if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL)
                      {
                      // Build the first part of the time
                      strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval);

                      // Add the milliseconds part and build the time string
                      snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds);
                      }

                      return timestamp;
                      }

                      int main()
                      {
                      int i = 0;
                      struct timespec sleeptime = {0, 5000000L};

                      struct Timestamp timestamp;

                      for (i=0; i < 20; i++)
                      {
                      timestamp = getTimestamp();
                      printf("Time is: %s n", timestamp.timestring);
                      nanosleep(&sleeptime, NULL);
                      }

                      return 0;
                      }





                      share|improve this answer




























                        0














                        I answered a similar question on Stack Overflow. I wanted a timestamp in a specific format, that could be obtained from a function repeatedly.



                        My implementation is different than the original posters, for very specific reasons. The goal is thus to create a simple timestamp structure and a function that can create it repeatedly without arguments. I think the function below does that.



                        A timestamp function should return a timestamp. It should not require the user to have know the necessary length of the char*. Such details should be hidden from the user. If not the user must manage the char* or keep tabs on how users of this function pass char* variables to it.



                        The function clock_gettime is the ideal POSIX function, but it is not universally supported. Avoid the other deprecated functions such as gettimeofday. As someone said earlier, ftime is not the function to use, and neither is gettimeofday.



                        I think the code below is mostly portable. I think the trick with timestamp functions is not so much portability, but avoiding the unnecessary usage of dynamically allocated memory. I think this is important because for embedded environments several rules preclude the usage of such C constructs.



                        Also, strcat requires an implicit search for ''. For the original solution strcat should cause no problems, but I generally avoid the use of strcat because of it's own problems.



                        My function returns a timestamp with a timestring (not ambiguous) and not a char* (ambiguous) - essentially this timestamp function is at a suitable code 'level', the reader knows what he is being presented with. I am not inter-mixing low and medium level code. I have a medium level type (timestamp) and a medium level function (getTimestamp) and it requires no arguments.



                        It would be 'nice' if clock_gettime had macro options for something like RAW_GPS_TIME, J2000_TAI_TIME, J2000_UTC_TIME and so forth, providing that such time sources were available, but this is another discussion.



                        struct Timestamp {
                        time_t seconds;
                        long milliseconds;
                        char timestring[32];
                        };


                        struct Timestamp getTimestamp()
                        {
                        char timebuffer[32] = {0};
                        struct timeval tv = {0};
                        struct tm *tmval = NULL;
                        struct tm gmtval = {0};
                        struct timespec curtime = {0};

                        struct Timestamp timestamp;

                        int i = 0;

                        // Get current time
                        clock_gettime(CLOCK_REALTIME, &curtime);


                        // Set the fields
                        timestamp.seconds = curtime.tv_sec;
                        timestamp.milliseconds = round(curtime.tv_nsec/1.0e6);

                        if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL)
                        {
                        // Build the first part of the time
                        strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval);

                        // Add the milliseconds part and build the time string
                        snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds);
                        }

                        return timestamp;
                        }

                        int main()
                        {
                        int i = 0;
                        struct timespec sleeptime = {0, 5000000L};

                        struct Timestamp timestamp;

                        for (i=0; i < 20; i++)
                        {
                        timestamp = getTimestamp();
                        printf("Time is: %s n", timestamp.timestring);
                        nanosleep(&sleeptime, NULL);
                        }

                        return 0;
                        }





                        share|improve this answer


























                          0












                          0








                          0






                          I answered a similar question on Stack Overflow. I wanted a timestamp in a specific format, that could be obtained from a function repeatedly.



                          My implementation is different than the original posters, for very specific reasons. The goal is thus to create a simple timestamp structure and a function that can create it repeatedly without arguments. I think the function below does that.



                          A timestamp function should return a timestamp. It should not require the user to have know the necessary length of the char*. Such details should be hidden from the user. If not the user must manage the char* or keep tabs on how users of this function pass char* variables to it.



                          The function clock_gettime is the ideal POSIX function, but it is not universally supported. Avoid the other deprecated functions such as gettimeofday. As someone said earlier, ftime is not the function to use, and neither is gettimeofday.



                          I think the code below is mostly portable. I think the trick with timestamp functions is not so much portability, but avoiding the unnecessary usage of dynamically allocated memory. I think this is important because for embedded environments several rules preclude the usage of such C constructs.



                          Also, strcat requires an implicit search for ''. For the original solution strcat should cause no problems, but I generally avoid the use of strcat because of it's own problems.



                          My function returns a timestamp with a timestring (not ambiguous) and not a char* (ambiguous) - essentially this timestamp function is at a suitable code 'level', the reader knows what he is being presented with. I am not inter-mixing low and medium level code. I have a medium level type (timestamp) and a medium level function (getTimestamp) and it requires no arguments.



                          It would be 'nice' if clock_gettime had macro options for something like RAW_GPS_TIME, J2000_TAI_TIME, J2000_UTC_TIME and so forth, providing that such time sources were available, but this is another discussion.



                          struct Timestamp {
                          time_t seconds;
                          long milliseconds;
                          char timestring[32];
                          };


                          struct Timestamp getTimestamp()
                          {
                          char timebuffer[32] = {0};
                          struct timeval tv = {0};
                          struct tm *tmval = NULL;
                          struct tm gmtval = {0};
                          struct timespec curtime = {0};

                          struct Timestamp timestamp;

                          int i = 0;

                          // Get current time
                          clock_gettime(CLOCK_REALTIME, &curtime);


                          // Set the fields
                          timestamp.seconds = curtime.tv_sec;
                          timestamp.milliseconds = round(curtime.tv_nsec/1.0e6);

                          if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL)
                          {
                          // Build the first part of the time
                          strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval);

                          // Add the milliseconds part and build the time string
                          snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds);
                          }

                          return timestamp;
                          }

                          int main()
                          {
                          int i = 0;
                          struct timespec sleeptime = {0, 5000000L};

                          struct Timestamp timestamp;

                          for (i=0; i < 20; i++)
                          {
                          timestamp = getTimestamp();
                          printf("Time is: %s n", timestamp.timestring);
                          nanosleep(&sleeptime, NULL);
                          }

                          return 0;
                          }





                          share|improve this answer














                          I answered a similar question on Stack Overflow. I wanted a timestamp in a specific format, that could be obtained from a function repeatedly.



                          My implementation is different than the original posters, for very specific reasons. The goal is thus to create a simple timestamp structure and a function that can create it repeatedly without arguments. I think the function below does that.



                          A timestamp function should return a timestamp. It should not require the user to have know the necessary length of the char*. Such details should be hidden from the user. If not the user must manage the char* or keep tabs on how users of this function pass char* variables to it.



                          The function clock_gettime is the ideal POSIX function, but it is not universally supported. Avoid the other deprecated functions such as gettimeofday. As someone said earlier, ftime is not the function to use, and neither is gettimeofday.



                          I think the code below is mostly portable. I think the trick with timestamp functions is not so much portability, but avoiding the unnecessary usage of dynamically allocated memory. I think this is important because for embedded environments several rules preclude the usage of such C constructs.



                          Also, strcat requires an implicit search for ''. For the original solution strcat should cause no problems, but I generally avoid the use of strcat because of it's own problems.



                          My function returns a timestamp with a timestring (not ambiguous) and not a char* (ambiguous) - essentially this timestamp function is at a suitable code 'level', the reader knows what he is being presented with. I am not inter-mixing low and medium level code. I have a medium level type (timestamp) and a medium level function (getTimestamp) and it requires no arguments.



                          It would be 'nice' if clock_gettime had macro options for something like RAW_GPS_TIME, J2000_TAI_TIME, J2000_UTC_TIME and so forth, providing that such time sources were available, but this is another discussion.



                          struct Timestamp {
                          time_t seconds;
                          long milliseconds;
                          char timestring[32];
                          };


                          struct Timestamp getTimestamp()
                          {
                          char timebuffer[32] = {0};
                          struct timeval tv = {0};
                          struct tm *tmval = NULL;
                          struct tm gmtval = {0};
                          struct timespec curtime = {0};

                          struct Timestamp timestamp;

                          int i = 0;

                          // Get current time
                          clock_gettime(CLOCK_REALTIME, &curtime);


                          // Set the fields
                          timestamp.seconds = curtime.tv_sec;
                          timestamp.milliseconds = round(curtime.tv_nsec/1.0e6);

                          if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL)
                          {
                          // Build the first part of the time
                          strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval);

                          // Add the milliseconds part and build the time string
                          snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds);
                          }

                          return timestamp;
                          }

                          int main()
                          {
                          int i = 0;
                          struct timespec sleeptime = {0, 5000000L};

                          struct Timestamp timestamp;

                          for (i=0; i < 20; i++)
                          {
                          timestamp = getTimestamp();
                          printf("Time is: %s n", timestamp.timestring);
                          nanosleep(&sleeptime, NULL);
                          }

                          return 0;
                          }






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Dec 19 '16 at 5:13









                          Jamal

                          30.2k11116226




                          30.2k11116226










                          answered Dec 17 '16 at 9:28









                          Xofo

                          1091




                          1091






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Code Review Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f120628%2ftimestamp-function-with-millisecond-precision%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              List directoties down one level, excluding some named directories and files

                              list processes belonging to a network namespace

                              list systemd RuntimeDirectory mounts