blob: 5518462952050939176d8682b6c753f8b0f96ebf [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or moreDate32Array
// 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.
using Apache.Arrow.Types;
using System;
using System.Collections.Generic;
using System.IO;
namespace Apache.Arrow
{
/// <summary>
/// The <see cref="Time64Array"/> class holds an array of <see cref="Int64" />, where each value is
/// stored as the number of microseconds/nanoseconds (depending on the Time64Type) since midnight.
/// </summary>
public class Time64Array : PrimitiveArray<long>
#if NET6_0_OR_GREATER
, IReadOnlyList<TimeOnly?>, ICollection<TimeOnly?>
#endif
{
/// <summary>
/// The <see cref="Builder"/> class can be used to fluently build <see cref="Time64Array"/> objects.
/// </summary>
public class Builder : TimeArrayBuilder<long, Time64Array, Builder>
{
private class TimeBuilder : PrimitiveArrayBuilder<long, Time64Array, TimeBuilder>
{
public Time64Type DataType { get; }
public TimeBuilder(Time64Type dataType) => DataType = dataType;
protected override Time64Array Build(
ArrowBuffer valueBuffer, ArrowBuffer nullBitmapBuffer,
int length, int nullCount, int offset) =>
new Time64Array(DataType, valueBuffer, nullBitmapBuffer, length, nullCount, offset);
}
public Builder()
: this(Time64Type.Default) { }
public Builder(TimeUnit unit)
: this((Time64Type)TimeType.FromTimeUnit(unit)) { }
/// <summary>
/// Construct a new instance of the <see cref="Builder"/> class.
/// </summary>
public Builder(Time64Type type)
: base(new TimeBuilder(type))
{
}
#if NET6_0_OR_GREATER
protected override long Convert(TimeOnly time)
{
return ((TimeBuilder)InnerBuilder).DataType.Unit.ConvertFromTicks(time.Ticks);
}
#endif
}
public Time64Array(
Time64Type type,
ArrowBuffer valueBuffer, ArrowBuffer nullBitmapBuffer,
int length, int nullCount, int offset)
: this(new ArrayData(type, length, nullCount, offset,
new[] { nullBitmapBuffer, valueBuffer }))
{ }
public Time64Array(ArrayData data)
: base(data)
{
data.EnsureDataType(ArrowTypeId.Time64);
}
public override void Accept(IArrowArrayVisitor visitor) => Accept(this, visitor);
/// <summary>
/// Get the time at the specified index as microseconds
/// </summary>
/// <param name="index">Index at which to get the time.</param>
/// <returns>Returns a <see cref="Int64" />, or <c>null</c> if there is no object at that index.
/// </returns>
public long? GetMicroSeconds(int index)
{
long? value = GetValue(index);
if (value == null)
{
return null;
}
var unit = ((Time64Type)Data.DataType).Unit;
return unit switch
{
TimeUnit.Microsecond => value,
TimeUnit.Nanosecond => value / 1_000,
_ => throw new InvalidDataException($"Unsupported time unit for Time64Type: {unit}")
};
}
/// <summary>
/// Get the time at the specified index as nanoseconds
/// </summary>
/// <param name="index">Index at which to get the time.</param>
/// <returns>Returns a <see cref="Int64" />, or <c>null</c> if there is no object at that index.
/// </returns>
public long? GetNanoSeconds(int index)
{
long? value = GetValue(index);
if (value == null)
{
return null;
}
var unit = ((Time64Type)Data.DataType).Unit;
return unit switch
{
TimeUnit.Microsecond => value * 1_000,
TimeUnit.Nanosecond => value,
_ => throw new InvalidDataException($"Unsupported time unit for Time64Type: {unit}")
};
}
#if NET6_0_OR_GREATER
/// <summary>
/// Get the time at the specified index as <see cref="TimeOnly"/>
/// </summary>
/// <remarks>
/// This may cause truncation of nanosecond values, as the resolution of TimeOnly is in 100-ns increments.
/// </remarks>
/// <param name="index">Index at which to get the time.</param>
/// <returns>Returns a <see cref="TimeOnly" />, or <c>null</c> if there is no object at that index.
/// </returns>
public TimeOnly? GetTime(int index)
{
long? value = GetValue(index);
if (value == null)
{
return null;
}
return new TimeOnly(((Time64Type)Data.DataType).Unit.ConvertToTicks(value.Value));
}
int IReadOnlyCollection<TimeOnly?>.Count => Length;
TimeOnly? IReadOnlyList<TimeOnly?>.this[int index] => GetTime(index);
IEnumerator<TimeOnly?> IEnumerable<TimeOnly?>.GetEnumerator()
{
for (int index = 0; index < Length; index++)
{
yield return GetTime(index);
};
}
int ICollection<TimeOnly?>.Count => Length;
bool ICollection<TimeOnly?>.IsReadOnly => true;
void ICollection<TimeOnly?>.Add(TimeOnly? item) => throw new NotSupportedException("Collection is read-only.");
bool ICollection<TimeOnly?>.Remove(TimeOnly? item) => throw new NotSupportedException("Collection is read-only.");
void ICollection<TimeOnly?>.Clear() => throw new NotSupportedException("Collection is read-only.");
bool ICollection<TimeOnly?>.Contains(TimeOnly? item)
{
for (int index = 0; index < Length; index++)
{
if (GetTime(index).Equals(item))
return true;
}
return false;
}
void ICollection<TimeOnly?>.CopyTo(TimeOnly?[] array, int arrayIndex)
{
for (int srcIndex = 0, destIndex = arrayIndex; srcIndex < Length; srcIndex++, destIndex++)
{
array[destIndex] = GetTime(srcIndex);
}
}
#endif
}
}