blob: 8b5279a10696f92c1fc2bfbe8b8ddc65b3f8dfd0 [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.
using Apache.Arrow.Types;
using System;
using System.Diagnostics;
using System.IO;
namespace Apache.Arrow
{
public class TimestampArray: PrimitiveArray<long>
{
private static readonly DateTimeOffset s_epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
public class Builder: PrimitiveArrayBuilder<DateTimeOffset, long, TimestampArray, Builder>
{
internal class TimestampBuilder : PrimitiveArrayBuilder<long, TimestampArray, TimestampBuilder>
{
internal TimestampBuilder(TimestampType type)
{
DataType = type ?? throw new ArgumentNullException(nameof(type));
}
protected TimestampType DataType { get; }
protected override TimestampArray Build(
ArrowBuffer valueBuffer, ArrowBuffer nullBitmapBuffer,
int length, int nullCount, int offset) =>
new TimestampArray(DataType, valueBuffer, nullBitmapBuffer,
length, nullCount, offset);
}
protected TimestampType DataType { get; }
public Builder()
: this(TimestampType.Default) { }
public Builder(TimeUnit unit, TimeZoneInfo timezone)
: this(new TimestampType(unit, timezone)) { }
public Builder(TimeUnit unit = TimeUnit.Millisecond, string timezone = "+00:00")
: this(new TimestampType(unit, timezone)) { }
public Builder(TimeUnit unit)
: this(new TimestampType(unit, (string) null)) { }
public Builder(TimestampType type)
: base(new TimestampBuilder(type))
{
DataType = type;
}
protected override long ConvertTo(DateTimeOffset value)
{
// We must return the absolute time since the UNIX epoch while
// respecting the timezone offset; the calculation is as follows:
//
// - Compute time span between epoch and specified time
// - Compute time divisions per tick
TimeSpan timeSpan = value - s_epoch;
long ticks = timeSpan.Ticks;
switch (DataType.Unit)
{
case TimeUnit.Nanosecond:
return ticks / 100;
case TimeUnit.Microsecond:
return ticks / TimeSpan.TicksPerMillisecond / 1000;
case TimeUnit.Millisecond:
return ticks / TimeSpan.TicksPerMillisecond;
case TimeUnit.Second:
return ticks / TimeSpan.TicksPerSecond;
default:
throw new InvalidOperationException($"unsupported time unit <{DataType.Unit}>");
}
}
}
public TimestampArray(
TimestampType type,
ArrowBuffer valueBuffer, ArrowBuffer nullBitmapBuffer,
int length, int nullCount, int offset)
: this(new ArrayData(type, length, nullCount, offset,
new[] {nullBitmapBuffer, valueBuffer})) { }
public TimestampArray(ArrayData data)
: base(data)
{
data.EnsureDataType(ArrowTypeId.Timestamp);
Debug.Assert(Data.DataType is TimestampType);
}
public override void Accept(IArrowArrayVisitor visitor) => Accept(this, visitor);
public DateTimeOffset GetTimestampUnchecked(int index)
{
var type = (TimestampType) Data.DataType;
long value = Values[index];
long ticks;
switch (type.Unit)
{
case TimeUnit.Nanosecond:
ticks = value * 100;
break;
case TimeUnit.Microsecond:
ticks = value * TimeSpan.TicksPerMillisecond * 1000;
break;
case TimeUnit.Millisecond:
ticks = value * TimeSpan.TicksPerMillisecond;
break;
case TimeUnit.Second:
ticks = value * TimeSpan.TicksPerSecond;
break;
default:
throw new InvalidDataException(
$"Unsupported timestamp unit <{type.Unit}>");
}
return new DateTimeOffset(s_epoch.Ticks + ticks, TimeSpan.Zero);
}
public DateTimeOffset? GetTimestamp(int index)
{
if (IsNull(index))
{
return null;
}
return GetTimestampUnchecked(index);
}
}
}