Skip to content

libfdatetime_floatingtime_copy_to_utf8_string: Fractional seconds (milliseconds, microseconds, nanoseconds) sometimes off #3

@siliconforks

Description

@siliconforks

Consider the following program:

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <libfdatetime.h>

void test_date(double days) {
  union {
    double x;
    uint64_t i;
  } u;

  u.x = days;

  libfdatetime_floatingtime_t * floatingtime = NULL;
  if (libfdatetime_floatingtime_initialize(&floatingtime, NULL) != 1) {
    fprintf(stderr, "libfdatetime_floatingtime_initialize failed\n");
    exit(EXIT_FAILURE);
  }

  if (libfdatetime_floatingtime_copy_from_64bit(floatingtime, u.i, NULL) != 1) {
    fprintf(stderr, "libfdatetime_floatingtime_copy_from_64bit failed\n");
    exit(EXIT_FAILURE);
  }

  uint8_t date_time_string[32];
  if (libfdatetime_floatingtime_copy_to_utf8_string(floatingtime,
        date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME |
        LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, NULL) != 1) {
    fprintf(stderr, "libfdatetime_floatingtime_copy_to_utf8_string failed\n");
    exit(EXIT_FAILURE);
  }

  printf("%f %" PRIx64 " %s\n", u.x, u.i, date_time_string);

  libfdatetime_floatingtime_free(&floatingtime, NULL);
}

int main(void) {
  for (int i = 0; i < 20; ++i) {
    test_date(45400 + i * 1e-6);
  }
  return 0;
}

This generates the following output:

45400.000000 40e62b0000000000 Apr 18, 2024 00:00:00.000000000
45400.000001 40e62b00000218df Apr 18, 2024 00:00:00.086144029
45400.000002 40e62b00000431be Apr 18, 2024 00:00:00.172032058
45400.000003 40e62b0000064a9d Apr 18, 2024 00:00:00.003200087
45400.000004 40e62b000008637c Apr 18, 2024 00:00:00.089088116
45400.000005 40e62b00000a7c5b Apr 18, 2024 00:00:00.176000146
45400.000006 40e62b00000c953a Apr 18, 2024 00:00:00.006144175
45400.000007 40e62b00000eae19 Apr 18, 2024 00:00:00.092032204
45400.000008 40e62b000010c6f8 Apr 18, 2024 00:00:00.179200233
45400.000009 40e62b000012dfd7 Apr 18, 2024 00:00:00.009088007
45400.000010 40e62b000014f8b6 Apr 18, 2024 00:00:00.096000036
45400.000011 40e62b0000171194 Apr 18, 2024 00:00:00.182143181
45400.000012 40e62b0000192a73 Apr 18, 2024 00:00:01.036031210
45400.000013 40e62b00001b4352 Apr 18, 2024 00:00:01.123199239
45400.000014 40e62b00001d5c31 Apr 18, 2024 00:00:01.209087012
45400.000015 40e62b00001f7510 Apr 18, 2024 00:00:01.039231042
45400.000016 40e62b0000218def Apr 18, 2024 00:00:01.126143071
45400.000017 40e62b000023a6ce Apr 18, 2024 00:00:01.212031100
45400.000018 40e62b000025bfad Apr 18, 2024 00:00:01.043199129
45400.000019 40e62b000027d88c Apr 18, 2024 00:00:01.129087159

The first few timestamps appear to be correct (00:00:00.00, 00:00:00.086..., 00:00:00.172...,), but then in the next timestamp the fraction is actually smaller (00:00:00.003...).

A similar thing happens for the timestamps after 00:00:01 - the first few seem about right (00:00:01.036..., 00:00:01.123..., 00:00:01.209...) but then the next timestamp goes down (00:00:01.039...).

I think the issue is that the milliseconds are sometimes getting corrupted because for some reason they are being cast to uint8_t:

/* There are 1000 milli seconds in a seconds correct the value to milli seconds
*/
floatingtimestamp *= 1000.0;
date_time_values->milli_seconds = (uint8_t) floatingtimestamp;
floatingtimestamp -= date_time_values->milli_seconds;

(Actually, even the fractional timestamps which appear to be correct may be off by a bit, because it seems that the microseconds and nanoseconds have the same issue.)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions