Skip to content
This repository has been archived by the owner on Feb 1, 2023. It is now read-only.

Commit

Permalink
Format timestamps with RFC3339 (#124)
Browse files Browse the repository at this point in the history
* Add support for printing timestamps as RFC3339

* Print stake lockup timestamps as timestamps

* Tweak format for human readability
  • Loading branch information
t-nelson authored May 3, 2020
1 parent 24a9b0a commit e77e8fe
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 2 deletions.
2 changes: 2 additions & 0 deletions libsol/include/sol/printer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ int print_summary(
size_t right_length
);

int print_timestamp(int64_t, char* out, size_t out_length);

int encode_base58(const void *in, size_t length, char *out, size_t maxoutlen);
6 changes: 6 additions & 0 deletions libsol/include/sol/transaction_summary.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ enum SummaryItemKind {
SummaryItemHash,
SummaryItemSizedString,
SummaryItemString,
SummaryItemTimestamp,
};

typedef struct SummaryItem SummaryItem;
Expand Down Expand Up @@ -105,3 +106,8 @@ void summary_item_set_string(
const char* title,
const char* value
);
void summary_item_set_timestamp(
SummaryItem* item,
const char* title,
int64_t value
);
5 changes: 5 additions & 0 deletions libsol/printer.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <string.h>
#include <limits.h>
#include "os_error.h"
#include "rfc3339.h"
#include "sol/printer.h"
#include "util.h"

Expand Down Expand Up @@ -217,3 +218,7 @@ int print_u64(uint64_t u64, char* out, size_t out_length) {

return 0;
}

int print_timestamp(int64_t timestamp, char* out, size_t out_length) {
return rfc3339_format(out, out_length, timestamp);
}
19 changes: 19 additions & 0 deletions libsol/printer_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,32 @@ void test_print_u64() {
assert(print_u64(0, NULL, 0) == 1);
}

void test_print_timestamp() {
#define RFC3339_MAX (4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1)
char out[RFC3339_MAX];
int64_t unix_epoch = 0;
const char* expect_unix_epoch = "1970-01-01 00:00:00";

assert(print_timestamp(unix_epoch, out, sizeof(out)) == 0);
assert_string_equal(out, expect_unix_epoch);

int64_t now = 1588374349;
const char* expect_now = "2020-05-01 23:05:49";

assert(print_timestamp(now, out, sizeof(out)) == 0);
assert_string_equal(out, expect_now);

assert(print_timestamp(0, out, sizeof(out) - 1) == 1);
}

int main() {
test_print_amount();
test_print_sized_string();
test_print_string();
test_print_summary();
test_print_i64();
test_print_u64();
test_print_timestamp();

printf("passed\n");
return 0;
Expand Down
104 changes: 104 additions & 0 deletions libsol/rfc3339.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2014 Christian Hansen <[email protected]>
* <https://github.com/chansen/c-timestamp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h>
#include "rfc3339.h"

static const uint16_t DayOffset[13] = {
0, 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275
};

/* Rata Die algorithm by Peter Baum */

static void
rdn_to_ymd(uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp) {
uint32_t Z, H, A, B;
uint16_t y, m, d;

Z = rdn + 306;
H = 100 * Z - 25;
A = H / 3652425;
B = A - (A >> 2);
y = (100 * B + H) / 36525;
d = B + Z - (1461 * y >> 2);
m = (535 * d + 48950) >> 14;
if (m > 12)
y++, m -= 12;

*yp = y;
*mp = m;
*dp = d - DayOffset[m];
}

#define EPOCH INT64_C(62135683200) /* 1970-01-01 00:00:00 */

int rfc3339_format(char *dst, size_t len, int64_t seconds) {
unsigned char *p;
uint64_t sec;
uint32_t rdn, v;
uint16_t y, m, d;
size_t dlen;

dlen = sizeof("YYYY-MM-DD hh:mm:ss") - 1;
if (dlen >= len)
return 1;

sec = seconds + EPOCH;
rdn = sec / 86400;

rdn_to_ymd(rdn, &y, &m, &d);

/*
* 1
* 0123456789012345678
* YYYY-MM-DDThh:mm:ss
*/
p = (unsigned char *)dst;
v = sec % 86400;
p[18] = '0' + (v % 10); v /= 10;
p[17] = '0' + (v % 6); v /= 6;
p[16] = ':';
p[15] = '0' + (v % 10); v /= 10;
p[14] = '0' + (v % 6); v /= 6;
p[13] = ':';
p[12] = '0' + (v % 10); v /= 10;
p[11] = '0' + (v % 10);
p[10] = ' ';
p[ 9] = '0' + (d % 10); d /= 10;
p[ 8] = '0' + (d % 10);
p[ 7] = '-';
p[ 6] = '0' + (m % 10); m /= 10;
p[ 5] = '0' + (m % 10);
p[ 4] = '-';
p[ 3] = '0' + (y % 10); y /= 10;
p[ 2] = '0' + (y % 10); y /= 10;
p[ 1] = '0' + (y % 10); y /= 10;
p[ 0] = '0' + (y % 10);
p += 19;

*p = 0;
return 0;
}

5 changes: 5 additions & 0 deletions libsol/rfc3339.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <stdint.h>

int rfc3339_format(char *dst, size_t len, int64_t seconds);
12 changes: 10 additions & 2 deletions libsol/stake_instruction.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,11 @@ static int print_stake_set_lockup_info(
enum StakeLockupPresent present = info->lockup.present;
if (present & StakeLockupHasTimestamp) {
item = transaction_summary_general_item();
summary_item_set_i64(item, "Lockup time", info->lockup.unix_timestamp);
summary_item_set_timestamp(
item,
"Lockup time",
info->lockup.unix_timestamp
);
}

if (present & StakeLockupHasEpoch) {
Expand Down Expand Up @@ -474,7 +478,11 @@ int print_stake_initialize_info(
}

item = transaction_summary_general_item();
summary_item_set_i64(item, "Lockup time", info->lockup.unix_timestamp);
summary_item_set_timestamp(
item,
"Lockup time",
info->lockup.unix_timestamp
);

item = transaction_summary_general_item();
summary_item_set_u64(item, "Lockup epoch", info->lockup.epoch);
Expand Down
17 changes: 17 additions & 0 deletions libsol/transaction_summary.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ void summary_item_set_string(
item->string = value;
}

void summary_item_set_timestamp(
SummaryItem* item,
const char* title,
int64_t value
) {
item->kind = SummaryItemTimestamp;
item->title = title;
item->i64 = value;
}

typedef struct TransactionSummary {
SummaryItem primary;
SummaryItem fee_payer;
Expand Down Expand Up @@ -241,6 +251,13 @@ static int transaction_summary_update_display_for_item(
TEXT_BUFFER_LENGTH
);
break;
case SummaryItemTimestamp:
BAIL_IF(print_timestamp(
item->i64,
G_transaction_summary_text,
TEXT_BUFFER_LENGTH
));
break;
}
print_string(item->title, G_transaction_summary_title, TITLE_SIZE);
return 0;
Expand Down
12 changes: 12 additions & 0 deletions libsol/transaction_summary_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ void test_summary_item_setters() {
assert(
strncmp("test", item.sized_string.string, item.sized_string.length) == 0
);

summary_item_set_timestamp(&item, "timestamp", 42);
assert(item.kind == SummaryItemTimestamp);
assert_string_equal(item.title, "timestamp");
assert(item.i64 == 42);
}

void test_summary_item_as_unused() {
Expand Down Expand Up @@ -80,6 +85,9 @@ void test_summary_item_as_unused() {

item.kind = SummaryItemString;
assert(summary_item_as_unused(&item) == NULL);

item.kind = SummaryItemTimestamp;
assert(summary_item_as_unused(&item) == NULL);
}

void test_transaction_summary_reset() {
Expand Down Expand Up @@ -189,6 +197,10 @@ void test_transaction_summary_update_display_for_item() {
summary_item_set_string(&item, "string", string);
assert(transaction_summary_update_display_for_item(&item, DisplayFlagNone) == 0);
assert_transaction_summary_display("string", "value");

summary_item_set_timestamp(&item, "timestamp", 42);
assert(transaction_summary_update_display_for_item(&item, DisplayFlagNone) == 0);
assert_transaction_summary_display("timestamp", "1970-01-01 00:00:42");
}

#define display_item_test_helper(item, item_index) \
Expand Down

0 comments on commit e77e8fe

Please sign in to comment.