mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-28 18:21:52 +00:00
234 lines
8.1 KiB
C
234 lines
8.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
#include <sys/stat.h>
|
|
#include "lib/mlr_globals.h"
|
|
#include "lib/mlrutil.h"
|
|
#include "lib/mlr_arch.h"
|
|
#include "lib/string_builder.h"
|
|
|
|
#define MYBUFLEN 256
|
|
|
|
// ----------------------------------------------------------------
|
|
static int f(char* float_string, char* format_string) {
|
|
double fseconds;
|
|
if (sscanf(float_string, "%lf", &fseconds) != 1) {
|
|
fprintf(stderr, "!dbl b04k!\n");
|
|
return 1;
|
|
}
|
|
|
|
time_t iseconds = (time_t) fseconds;
|
|
double fracsec = fseconds - iseconds;
|
|
|
|
struct tm tm = *gmtime(&iseconds);
|
|
|
|
// xxx see if %nS is a substring
|
|
// if not then do it like always (w/ malloc)
|
|
// if so:
|
|
// * copy subformats left & right of the %nS
|
|
// * strftime each
|
|
// * myself format the middle
|
|
// * sb_append
|
|
|
|
char* middle_format = NULL;
|
|
char* right_subformat = NULL;
|
|
for (char* p = format_string; *p; p++) {
|
|
if (p[0] == '%' && p[1] >= '1' && p[1] <= '9' && p[2] == 'S') {
|
|
middle_format = p;
|
|
right_subformat = &p[3];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (middle_format == NULL) {
|
|
char* output_string = mlr_malloc_or_die(MYBUFLEN);
|
|
|
|
int written_length = strftime(output_string, MYBUFLEN, format_string, &tm);
|
|
if (written_length > MYBUFLEN || written_length == 0) {
|
|
fprintf(stderr, "Could not strftime(\"%s\", \"%s\").\n",
|
|
float_string, format_string);
|
|
return 1;
|
|
} else {
|
|
printf("%s %s -> %s\n", float_string, format_string, output_string);
|
|
}
|
|
|
|
free(output_string);
|
|
|
|
} else {
|
|
int left_subformat_length = middle_format - format_string;
|
|
char* left_subformat = mlr_malloc_or_die(left_subformat_length + 1);
|
|
memcpy(left_subformat, format_string, left_subformat_length);
|
|
left_subformat[left_subformat_length] = 0;
|
|
char left_formatted[MYBUFLEN];
|
|
char right_formatted[MYBUFLEN];
|
|
|
|
if (*left_subformat == 0) {
|
|
*left_formatted = 0;
|
|
} else {
|
|
int written_length = strftime(left_formatted, MYBUFLEN, left_subformat, &tm);
|
|
printf("LEFT SUBFORMAT \"%s\"\n", left_subformat);
|
|
if (written_length > MYBUFLEN || written_length == 0) {
|
|
fprintf(stderr, "Could not strftime(\"%s\", \"%s\").\n",
|
|
float_string, left_subformat);
|
|
return 1;
|
|
}
|
|
}
|
|
free(left_subformat);
|
|
|
|
char middle_int_formatted[16];
|
|
char* middle_int_format = "%S";
|
|
printf("MIDDLI SUBFORMAT \"%s\"\n", middle_int_format);
|
|
int written_length = strftime(middle_int_formatted, sizeof(middle_int_formatted), middle_int_format, &tm);
|
|
if (written_length > MYBUFLEN || written_length == 0) {
|
|
fprintf(stderr, "Could not strftime(\"%s\", \"%s\").\n",
|
|
float_string, middle_int_format);
|
|
return 1;
|
|
}
|
|
|
|
char middle_sprintf_format[] = "%.xlf";
|
|
char middle_fractional_formatted[16];
|
|
middle_sprintf_format[2] = middle_format[1];
|
|
printf("MIDDLE_SPRINTF_FORMAT \"%s\"\n", middle_sprintf_format);
|
|
sprintf(middle_fractional_formatted, middle_sprintf_format, fracsec);
|
|
|
|
if (*right_subformat == 0) {
|
|
*right_formatted = 0;
|
|
} else {
|
|
printf("RIGHT SUBFORMAT \"%s\"\n", right_subformat);
|
|
int written_length = strftime(right_formatted, MYBUFLEN, right_subformat, &tm);
|
|
if (written_length > MYBUFLEN || written_length == 0) {
|
|
fprintf(stderr, "Could not strftime(\"%s\", \"%s\").\n",
|
|
float_string, right_subformat);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
string_builder_t* psb = sb_alloc(32);
|
|
sb_append_string(psb, left_formatted);
|
|
sb_append_string(psb, middle_int_formatted);
|
|
sb_append_string(psb, &middle_fractional_formatted[1]); // xxx comment
|
|
sb_append_string(psb, right_formatted);
|
|
char* output_string = sb_finish(psb);
|
|
sb_free(psb);
|
|
|
|
printf("LEFT OUT \"%s\"\n", left_formatted);
|
|
printf("MIDDLI OUT \"%s\"\n", middle_int_formatted);
|
|
printf("MIDDLF OUT \"%s\"\n", middle_fractional_formatted);
|
|
printf("RIGHT OUT \"%s\"\n", right_formatted);
|
|
|
|
printf("%s %s -> %s\n", float_string, format_string, output_string);
|
|
free(output_string);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
static int p(char* time_string, char* format_string) {
|
|
|
|
struct tm tm;
|
|
memset(&tm, 0, sizeof(tm));
|
|
|
|
// xxx cmt try the non-floating-point-seconds case first and return quickly if so.
|
|
char* strptime_retval = mlr_arch_strptime(time_string, format_string, &tm);
|
|
if (strptime_retval != NULL) {
|
|
if (*strptime_retval != 0) { // xxx extraneous
|
|
fprintf(stderr, "%s: could not strptime(\"%s\", \"%s\"). See \"%s --help-function strptime\".\n",
|
|
MLR_GLOBALS.bargv0, time_string, format_string, MLR_GLOBALS.bargv0);
|
|
exit(1);
|
|
}
|
|
time_t iseconds = mlr_arch_timegm(&tm);
|
|
printf("%s, %s -> %u, \"%s\"\n", time_string, format_string, (unsigned)iseconds, strptime_retval);
|
|
return 0;
|
|
}
|
|
|
|
char* pS = strstr(format_string, "%S");
|
|
if (pS == NULL) {
|
|
// Couldn't have been because of floating-point-seconds stuff. No reason to try any harder.
|
|
fprintf(stderr, "%s: could not strptime(\"%s\", \"%s\"). See \"%s --help-function strptime\".\n",
|
|
MLR_GLOBALS.bargv0, time_string, format_string, MLR_GLOBALS.bargv0);
|
|
exit(1);
|
|
}
|
|
|
|
// xxx
|
|
// Input is "2017-04-09T00:51:09.123456 TZBLAHBLAH"
|
|
// with format "%Y-%m-%dT%H:%M:%S TZBLAHBLAH"
|
|
|
|
// 1. Copy the format up to the %S but with nothing else after. This is temporary to help us locate
|
|
// the fractional-seconds part of the input string.
|
|
// Example temporary format: "%Y-%m-%dT%H:%M:%S"
|
|
|
|
int truncated_format_string_length = pS - format_string + 2;
|
|
char* truncated_format_string = mlr_malloc_or_die(truncated_format_string_length + 1);
|
|
memcpy(truncated_format_string, format_string, truncated_format_string_length);
|
|
truncated_format_string[truncated_format_string_length] = 0;
|
|
printf("ORIGINAL FORMAT \"%s\"\n", format_string);
|
|
printf("TRUNCATED FORMAT \"%s\"\n", truncated_format_string);
|
|
|
|
// 2. strptime using that truncated format and ignore the tm. Only look at the string return value.
|
|
// Example return value: ".123456 TZBLAHBLAH"
|
|
|
|
strptime_retval = mlr_arch_strptime(time_string, truncated_format_string, &tm);
|
|
if (strptime_retval == NULL) {
|
|
fprintf(stderr, "%s: could not strptime(\"%s\", \"%s\"). See \"%s --help-function strptime\".\n",
|
|
MLR_GLOBALS.bargv0, time_string, format_string, MLR_GLOBALS.bargv0);
|
|
exit(1);
|
|
}
|
|
printf("STRPTIME TEMP RETVAL \"%s\"\n", strptime_retval);
|
|
|
|
// 3. strtod the return value to find the fractional-seconds part, and whatever's after.
|
|
// Example fractional-seconds part: ".123456"
|
|
// Example stuff after: " TZBLAHBLAH"
|
|
|
|
char* stuff_after = NULL;
|
|
double fractional_seconds = strtod(strptime_retval, &stuff_after);
|
|
printf("FRACTIONAL SECONDS %.6lf\n", fractional_seconds);
|
|
printf("STUFF AFTER \"%s\"\n", stuff_after);
|
|
|
|
// 4. Make a copy of the input string with the fractional seconds elided.
|
|
// Example: "2017-04-09T00:51:09 TZBLAHBLAH"
|
|
char* elided_fraction_input = mlr_malloc_or_die(strlen(time_string) + 1);
|
|
int input_length_to_fractional_seconds = strptime_retval - time_string;
|
|
memcpy(elided_fraction_input, time_string, input_length_to_fractional_seconds);
|
|
strcpy(&elided_fraction_input[input_length_to_fractional_seconds], stuff_after);
|
|
printf("ELIDE \"%s\"\n", elided_fraction_input);
|
|
|
|
// 5. strptime the elided-fraction input string using the original format string. Get the tm.
|
|
memset(&tm, 0, sizeof(tm));
|
|
strptime_retval = mlr_arch_strptime(elided_fraction_input, format_string, &tm);
|
|
if (strptime_retval == NULL) {
|
|
fprintf(stderr, "%s: could not strptime(\"%s\", \"%s\"). See \"%s --help-function strptime\".\n",
|
|
MLR_GLOBALS.bargv0, time_string, format_string, MLR_GLOBALS.bargv0);
|
|
exit(1);
|
|
}
|
|
printf("STRPTIME ELIDE RETVAL \"%s\"\n", strptime_retval);
|
|
|
|
// 6. Convert the tm to a time_t (seconds since the epoch) and then add the fractional seceonds.
|
|
time_t iseconds = mlr_arch_timegm(&tm);
|
|
printf("ISECONDS %u\n", (unsigned)iseconds);
|
|
double fseconds = iseconds + fractional_seconds;
|
|
printf("FSECONDS %.6lf\n", fseconds);
|
|
printf("%s %s -> %.6lf\n", time_string, format_string, fseconds);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int main(int argc, char **argv) {
|
|
if (argc != 4) {
|
|
fprintf(stderr, "c!=4 b04k!\n");
|
|
exit(1);
|
|
}
|
|
if (!strcmp(argv[1], "f")) {
|
|
return f(argv[2], argv[3]);
|
|
} else if (!strcmp(argv[1], "p")) {
|
|
return p(argv[2], argv[3]);
|
|
} else {
|
|
fprintf(stderr, "f/p b04k!\n");
|
|
exit(1);
|
|
}
|
|
|
|
return 0;
|
|
}
|