Skip to content

Commit

Permalink
nanos in timestamp INT96 can be negative
Browse files Browse the repository at this point in the history
  • Loading branch information
liujiayi771 committed Mar 23, 2024
1 parent 0cb618e commit 8704300
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 6 deletions.
6 changes: 3 additions & 3 deletions velox/dwio/parquet/reader/PageReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,15 +388,15 @@ void PageReader::prepareDictionary(const PageHeader& pageHeader) {
for (auto i = dictionary_.numValues - 1; i >= 0; --i) {
// Convert the timestamp into seconds and nanos since the Unix epoch,
// 00:00:00.000000 on 1 January 1970.
uint64_t nanos;
int64_t nanos;
memcpy(
&nanos,
parquetValues + i * sizeof(Int96Timestamp),
sizeof(uint64_t));
sizeof(int64_t));
int32_t days;
memcpy(
&days,
parquetValues + i * sizeof(Int96Timestamp) + sizeof(uint64_t),
parquetValues + i * sizeof(Int96Timestamp) + sizeof(int64_t),
sizeof(int32_t));

values[i] = Timestamp::fromDaysAndNanos(days, nanos);
Expand Down
9 changes: 6 additions & 3 deletions velox/type/Timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ struct Timestamp {

constexpr Timestamp() : seconds_(0), nanos_(0) {}

Timestamp(int64_t seconds, uint64_t nanos)
Timestamp(int64_t seconds, int64_t nanos)
: seconds_(seconds), nanos_(nanos) {
VELOX_USER_DCHECK_GE(
seconds, kMinSeconds, "Timestamp seconds out of range");
Expand All @@ -110,16 +110,19 @@ struct Timestamp {
VELOX_USER_DCHECK_LE(nanos, kMaxNanos, "Timestamp nanos out of range");
}

static Timestamp fromDaysAndNanos(int32_t days, uint64_t nanos) {
static Timestamp fromDaysAndNanos(int32_t days, int64_t nanos) {
static constexpr int64_t kJulianToUnixEpochDays = 2440588LL;
static constexpr int64_t kSecondsPerDay = 86400LL;
static constexpr int64_t kNanosPerSecond =
Timestamp::kNanosecondsInMillisecond * Timestamp::kMillisecondsInSecond;

int64_t seconds = (days - kJulianToUnixEpochDays) * kSecondsPerDay;
if (nanos > Timestamp::kMaxNanos) {
if (nanos > static_cast<int64_t>(Timestamp::kMaxNanos)) {
seconds += nanos / kNanosPerSecond;
nanos -= (nanos / kNanosPerSecond) * kNanosPerSecond;
} else if (nanos < 0) {
seconds += (nanos / kNanosPerSecond - 1);
nanos -= (nanos / kNanosPerSecond - 1) * kNanosPerSecond;
}

return Timestamp(seconds, nanos);
Expand Down

0 comments on commit 8704300

Please sign in to comment.