blob: f827cd98e4949ab0d02a51c885438bebec0b0d4c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Apache.Ignite.Internal.Table;
using System;
using Ignite.Sql;
using NodaTime;
/// <summary>
/// Temporal type utils.
/// </summary>
internal static class TemporalTypes
{
/// <summary>
/// Max <see cref="ColumnType.Time"/> type precision.
/// </summary>
public const int MaxTimePrecision = 9;
/// <summary>
/// Normalize nanoseconds regarding the precision.
/// </summary>
/// <param name="nanos">Nanoseconds.</param>
/// <param name="precision">Precision.</param>
/// <returns>Normalized nanoseconds.</returns>
public static int NormalizeNanos(int nanos, int precision) =>
precision switch
{
0 => 0,
1 => (nanos / 100_000_000) * 100_000_000, // 100ms precision.
2 => (nanos / 10_000_000) * 10_000_000, // 10ms precision.
3 => (nanos / 1_000_000) * 1_000_000, // 1ms precision.
4 => (nanos / 100_000) * 100_000, // 100us precision.
5 => (nanos / 10_000) * 10_000, // 10us precision.
6 => (nanos / 1_000) * 1_000, // 1us precision.
7 => (nanos / 100) * 100, // 100ns precision.
8 => (nanos / 10) * 10, // 10ns precision.
9 => nanos, // 1ns precision
_ => throw new ArgumentException("Unsupported fractional seconds precision: " + precision)
};
/// <summary>
/// Deconstructs Instant into seconds and nanoseconds.
/// </summary>
/// <param name="value">Value.</param>
/// <param name="precision">Column precision.</param>
/// <returns>Seconds and nanos.</returns>
public static (long Seconds, int Nanos) ToSecondsAndNanos(this Instant value, int precision)
{
// Logic taken from
// https://github.com/nodatime/nodatime.serialization/blob/main/src/NodaTime.Serialization.Protobuf/NodaExtensions.cs#L69
// (Apache License).
// See discussion: https://github.com/nodatime/nodatime/issues/1644#issuecomment-1260524451
long seconds = value.ToUnixTimeSeconds();
Duration remainder = value - Instant.FromUnixTimeSeconds(seconds);
int nanos = NormalizeNanos((int)remainder.NanosecondOfDay, precision);
return (seconds, nanos);
}
}