This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-swift.git
The following commit(s) were added to refs/heads/main by this push:
new 476d1c0 feat: Add support for Timestamp data type (#33)
476d1c0 is described below
commit 476d1c0a44a460c0c50357618e63c89240088e9c
Author: Marco Antonio <[email protected]>
AuthorDate: Mon Jun 16 18:44:32 2025 -0300
feat: Add support for Timestamp data type (#33)
### Rationale for this change
Currently, the Swift implementation of Arrow does not support Timestamp,
although they are available in the base C interface. This PR attempts to
add its support by following the current implemented design pattern.
### What changes are included in this PR?
1. `TimestampArray` with some basic formatting utilities
2. `TimestampArrayBuilder`
3. `Timestamp` alias
4. `ArrowTimestampUnit`, which includes extensively all the variants
(seconds, milliseconds, microseconds and nanoseconds)
5. `ArrowTypeTimestamp` from base `Arrow`
6. `ArrowType` support for timestamp
7. `ArrowWriterHelper` support for timestamp
8. `fromProto` support for timestamp
It properly handles the presence or absence of `timezone`.
### Are these changes tested?
Tests are included in both `ArrayTests.swift` and `CDataTests.swift`.
### Are there any user-facing changes?
Yes - users can now work with Timestamp data types in Swift Arrow
implementations. This is additive and doesn't break existing
functionality.
Closes #32.
---------
Co-authored-by: Marco <[email protected]>
Co-authored-by: Sutou Kouhei <[email protected]>
---
Arrow/Sources/Arrow/ArrowArray.swift | 80 +++++++++++++++++++++++++++++
Arrow/Sources/Arrow/ArrowArrayBuilder.swift | 15 ++++++
Arrow/Sources/Arrow/ArrowReaderHelper.swift | 38 +++++++++++++-
Arrow/Sources/Arrow/ArrowType.swift | 69 +++++++++++++++++++++++++
Arrow/Sources/Arrow/ArrowWriterHelper.swift | 28 ++++++++++
Arrow/Sources/Arrow/ProtoUtil.swift | 16 ++++++
Arrow/Tests/ArrowTests/ArrayTests.swift | 70 +++++++++++++++++++++++++
Arrow/Tests/ArrowTests/CDataTests.swift | 6 ++-
8 files changed, 320 insertions(+), 2 deletions(-)
diff --git a/Arrow/Sources/Arrow/ArrowArray.swift
b/Arrow/Sources/Arrow/ArrowArray.swift
index 4fc1b8b..d4ee873 100644
--- a/Arrow/Sources/Arrow/ArrowArray.swift
+++ b/Arrow/Sources/Arrow/ArrowArray.swift
@@ -105,6 +105,8 @@ public class ArrowArrayHolderImpl: ArrowArrayHolder {
return try ArrowArrayHolderImpl(Time32Array(with))
case .time64:
return try ArrowArrayHolderImpl(Time64Array(with))
+ case .timestamp:
+ return try ArrowArrayHolderImpl(TimestampArray(with))
case .string:
return try ArrowArrayHolderImpl(StringArray(with))
case .boolean:
@@ -233,6 +235,84 @@ public class Date64Array: ArrowArray<Date> {
public class Time32Array: FixedArray<Time32> {}
public class Time64Array: FixedArray<Time64> {}
+public class TimestampArray: FixedArray<Timestamp> {
+
+ public struct FormattingOptions: Equatable {
+ public var dateFormat: String = "yyyy-MM-dd HH:mm:ss.SSS"
+ public var locale: Locale = .current
+ public var includeTimezone: Bool = true
+ public var fallbackToRaw: Bool = true
+
+ public init(dateFormat: String = "yyyy-MM-dd HH:mm:ss.SSS",
+ locale: Locale = .current,
+ includeTimezone: Bool = true,
+ fallbackToRaw: Bool = true) {
+ self.dateFormat = dateFormat
+ self.locale = locale
+ self.includeTimezone = includeTimezone
+ self.fallbackToRaw = fallbackToRaw
+ }
+
+ public static func == (lhs: FormattingOptions, rhs: FormattingOptions)
-> Bool {
+ return lhs.dateFormat == rhs.dateFormat &&
+ lhs.locale.identifier == rhs.locale.identifier &&
+ lhs.includeTimezone == rhs.includeTimezone &&
+ lhs.fallbackToRaw == rhs.fallbackToRaw
+ }
+ }
+
+ private var cachedFormatter: DateFormatter?
+ private var cachedOptions: FormattingOptions?
+
+ public func formattedDate(at index: UInt, options: FormattingOptions =
FormattingOptions()) -> String? {
+ guard let timestamp = self[index] else { return nil }
+
+ guard let timestampType = self.arrowData.type as? ArrowTypeTimestamp
else {
+ return options.fallbackToRaw ? "\(timestamp)" : nil
+ }
+
+ let date = dateFromTimestamp(timestamp, unit: timestampType.unit)
+
+ if cachedFormatter == nil || cachedOptions != options {
+ let formatter = DateFormatter()
+ formatter.dateFormat = options.dateFormat
+ formatter.locale = options.locale
+ if options.includeTimezone, let timezone = timestampType.timezone {
+ formatter.timeZone = TimeZone(identifier: timezone)
+ }
+ cachedFormatter = formatter
+ cachedOptions = options
+ }
+
+ return cachedFormatter?.string(from: date)
+ }
+
+ private func dateFromTimestamp(_ timestamp: Int64, unit:
ArrowTimestampUnit) -> Date {
+ let timeInterval: TimeInterval
+
+ switch unit {
+ case .seconds:
+ timeInterval = TimeInterval(timestamp)
+ case .milliseconds:
+ timeInterval = TimeInterval(timestamp) / 1_000
+ case .microseconds:
+ timeInterval = TimeInterval(timestamp) / 1_000_000
+ case .nanoseconds:
+ timeInterval = TimeInterval(timestamp) / 1_000_000_000
+ }
+
+ return Date(timeIntervalSince1970: timeInterval)
+ }
+
+ public override func asString(_ index: UInt) -> String {
+ if let formatted = formattedDate(at: index) {
+ return formatted
+ }
+
+ return super.asString(index)
+ }
+}
+
public class BinaryArray: ArrowArray<Data> {
public struct Options {
public var printAsHex = false
diff --git a/Arrow/Sources/Arrow/ArrowArrayBuilder.swift
b/Arrow/Sources/Arrow/ArrowArrayBuilder.swift
index 005cad7..493e43a 100644
--- a/Arrow/Sources/Arrow/ArrowArrayBuilder.swift
+++ b/Arrow/Sources/Arrow/ArrowArrayBuilder.swift
@@ -119,6 +119,12 @@ public class Time64ArrayBuilder:
ArrowArrayBuilder<FixedBufferBuilder<Time64>, T
}
}
+public class TimestampArrayBuilder:
ArrowArrayBuilder<FixedBufferBuilder<Int64>, TimestampArray> {
+ fileprivate convenience init(_ unit: ArrowTimestampUnit, timezone: String?
= nil) throws {
+ try self.init(ArrowTypeTimestamp(unit, timezone: timezone))
+ }
+}
+
public class StructArrayBuilder: ArrowArrayBuilder<StructBufferBuilder,
StructArray> {
let builders: [any ArrowArrayHolderBuilder]
let fields: [ArrowField]
@@ -279,6 +285,11 @@ public class ArrowArrayBuilders {
throw ArrowError.invalid("Expected arrow type for
\(arrowType.id) not found")
}
return try Time64ArrayBuilder(timeType.unit)
+ case .timestamp:
+ guard let timestampType = arrowType as? ArrowTypeTimestamp else {
+ throw ArrowError.invalid("Expected arrow type for
\(arrowType.id) not found")
+ }
+ return try TimestampArrayBuilder(timestampType.unit)
default:
throw ArrowError.unknownType("Builder not found for arrow type:
\(arrowType.id)")
}
@@ -338,4 +349,8 @@ public class ArrowArrayBuilders {
public static func loadTime64ArrayBuilder(_ unit: ArrowTime64Unit) throws
-> Time64ArrayBuilder {
return try Time64ArrayBuilder(unit)
}
+
+ public static func loadTimestampArrayBuilder(_ unit: ArrowTimestampUnit,
timezone: String? = nil) throws -> TimestampArrayBuilder {
+ return try TimestampArrayBuilder(unit, timezone: timezone)
+ }
}
diff --git a/Arrow/Sources/Arrow/ArrowReaderHelper.swift
b/Arrow/Sources/Arrow/ArrowReaderHelper.swift
index 78ad280..37f4680 100644
--- a/Arrow/Sources/Arrow/ArrowReaderHelper.swift
+++ b/Arrow/Sources/Arrow/ArrowReaderHelper.swift
@@ -90,6 +90,24 @@ private func makeTimeHolder(_ field: ArrowField,
}
}
+private func makeTimestampHolder(_ field: ArrowField,
+ buffers: [ArrowBuffer],
+ nullCount: UInt
+) -> Result<ArrowArrayHolder, ArrowError> {
+ do {
+ if let arrowType = field.type as? ArrowTypeTimestamp {
+ let arrowData = try ArrowData(arrowType, buffers: buffers,
nullCount: nullCount)
+ return .success(ArrowArrayHolderImpl(try
TimestampArray(arrowData)))
+ } else {
+ return .failure(.invalid("Incorrect field type for timestamp:
\(field.type)"))
+ }
+ } catch let error as ArrowError {
+ return .failure(error)
+ } catch {
+ return .failure(.unknownError("\(error)"))
+ }
+}
+
private func makeBoolHolder(_ buffers: [ArrowBuffer],
nullCount: UInt) -> Result<ArrowArrayHolder,
ArrowError> {
do {
@@ -186,6 +204,8 @@ func makeArrayHolder( // swiftlint:disable:this
cyclomatic_complexity
return makeDateHolder(field, buffers: buffers, nullCount: nullCount)
case .time32, .time64:
return makeTimeHolder(field, buffers: buffers, nullCount: nullCount)
+ case .timestamp:
+ return makeTimestampHolder(field, buffers: buffers, nullCount:
nullCount)
case .strct:
return makeStructHolder(field, buffers: buffers, nullCount: nullCount,
children: children!, rbLength: rbLength)
default:
@@ -203,7 +223,7 @@ func makeBuffer(_ buffer: org_apache_arrow_flatbuf_Buffer,
fileData: Data,
func isFixedPrimitive(_ type: org_apache_arrow_flatbuf_Type_) -> Bool {
switch type {
- case .int, .bool, .floatingpoint, .date, .time:
+ case .int, .bool, .floatingpoint, .date, .time, .timestamp:
return true
default:
return false
@@ -261,6 +281,22 @@ func findArrowType( // swiftlint:disable:this
cyclomatic_complexity function_bod
}
return ArrowTypeTime64(timeType.unit == .microsecond ? .microseconds :
.nanoseconds)
+ case .timestamp:
+ let timestampType = field.type(type:
org_apache_arrow_flatbuf_Timestamp.self)!
+ let arrowUnit: ArrowTimestampUnit
+ switch timestampType.unit {
+ case .second:
+ arrowUnit = .seconds
+ case .millisecond:
+ arrowUnit = .milliseconds
+ case .microsecond:
+ arrowUnit = .microseconds
+ case .nanosecond:
+ arrowUnit = .nanoseconds
+ }
+
+ let timezone = timestampType.timezone
+ return ArrowTypeTimestamp(arrowUnit, timezone: timezone)
case .struct_:
_ = field.type(type: org_apache_arrow_flatbuf_Struct_.self)!
var fields = [ArrowField]()
diff --git a/Arrow/Sources/Arrow/ArrowType.swift
b/Arrow/Sources/Arrow/ArrowType.swift
index b44f859..9b6091f 100644
--- a/Arrow/Sources/Arrow/ArrowType.swift
+++ b/Arrow/Sources/Arrow/ArrowType.swift
@@ -21,6 +21,7 @@ public typealias Time32 = Int32
public typealias Time64 = Int64
public typealias Date32 = Int32
public typealias Date64 = Int64
+public typealias Timestamp = Int64
func FlatBuffersVersion_23_1_4() { // swiftlint:disable:this identifier_name
}
@@ -65,6 +66,7 @@ public enum ArrowTypeId {
case strct
case time32
case time64
+ case timestamp
case time
case uint16
case uint32
@@ -122,6 +124,47 @@ public class ArrowTypeTime64: ArrowType {
}
}
+public enum ArrowTimestampUnit {
+ case seconds
+ case milliseconds
+ case microseconds
+ case nanoseconds
+}
+
+public class ArrowTypeTimestamp: ArrowType {
+ let unit: ArrowTimestampUnit
+ let timezone: String?
+
+ public init(_ unit: ArrowTimestampUnit, timezone: String? = nil) {
+ self.unit = unit
+ self.timezone = timezone
+
+ super.init(ArrowType.ArrowTimestamp)
+ }
+
+ public convenience init(type: ArrowTypeId) {
+ self.init(.milliseconds, timezone: nil)
+ }
+
+ public override var cDataFormatId: String {
+ get throws {
+ let unitChar: String
+ switch self.unit {
+ case .seconds: unitChar = "s"
+ case .milliseconds: unitChar = "m"
+ case .microseconds: unitChar = "u"
+ case .nanoseconds: unitChar = "n"
+ }
+
+ if let timezone = self.timezone {
+ return "ts\(unitChar):\(timezone)"
+ } else {
+ return "ts\(unitChar)"
+ }
+ }
+ }
+}
+
public class ArrowNestedType: ArrowType {
let fields: [ArrowField]
public init(_ info: ArrowType.Info, fields: [ArrowField]) {
@@ -150,6 +193,7 @@ public class ArrowType {
public static let ArrowBinary = Info.variableInfo(ArrowTypeId.binary)
public static let ArrowTime32 = Info.timeInfo(ArrowTypeId.time32)
public static let ArrowTime64 = Info.timeInfo(ArrowTypeId.time64)
+ public static let ArrowTimestamp = Info.timeInfo(ArrowTypeId.timestamp)
public static let ArrowStruct = Info.complexInfo(ArrowTypeId.strct)
public init(_ info: ArrowType.Info) {
@@ -270,6 +314,8 @@ public class ArrowType {
return MemoryLayout<Time32>.stride
case .time64:
return MemoryLayout<Time64>.stride
+ case .timestamp:
+ return MemoryLayout<Timestamp>.stride
case .binary:
return MemoryLayout<Int8>.stride
case .string:
@@ -320,6 +366,11 @@ public class ArrowType {
return try time64.cDataFormatId
}
return "ttu"
+ case ArrowTypeId.timestamp:
+ if let timestamp = self as? ArrowTypeTimestamp {
+ return try timestamp.cDataFormatId
+ }
+ return "tsu"
case ArrowTypeId.binary:
return "z"
case ArrowTypeId.string:
@@ -366,6 +417,24 @@ public class ArrowType {
return ArrowTypeTime64(.microseconds)
} else if from == "ttn" {
return ArrowTypeTime64(.nanoseconds)
+ } else if from.starts(with: "ts") {
+ let components = from.split(separator: ":", maxSplits: 1)
+ guard let unitPart = components.first, unitPart.count == 3 else {
+ throw ArrowError.invalid("Invalid timestamp format '\(from)'.
Expected format 'ts[s|m|u|n][:timezone]'")
+ }
+
+ let unitChar = unitPart.suffix(1)
+ let unit: ArrowTimestampUnit
+ switch unitChar {
+ case "s": unit = .seconds
+ case "m": unit = .milliseconds
+ case "u": unit = .microseconds
+ case "n": unit = .nanoseconds
+ default: throw ArrowError.invalid("Unrecognized timestamp unit
'\(unitChar)'. Expected 's', 'm', 'u', or 'n'.")
+ }
+
+ let timezone = components.count > 1 ? String(components[1]) : nil
+ return ArrowTypeTimestamp(unit, timezone: timezone)
} else if from == "z" {
return ArrowType(ArrowType.ArrowBinary)
} else if from == "u" {
diff --git a/Arrow/Sources/Arrow/ArrowWriterHelper.swift
b/Arrow/Sources/Arrow/ArrowWriterHelper.swift
index b3fa2b4..7ecb3ab 100644
--- a/Arrow/Sources/Arrow/ArrowWriterHelper.swift
+++ b/Arrow/Sources/Arrow/ArrowWriterHelper.swift
@@ -41,6 +41,8 @@ func toFBTypeEnum(_ arrowType: ArrowType) ->
Result<org_apache_arrow_flatbuf_Typ
return .success(org_apache_arrow_flatbuf_Type_.date)
case .time32, .time64:
return .success(org_apache_arrow_flatbuf_Type_.time)
+ case .timestamp:
+ return .success(org_apache_arrow_flatbuf_Type_.timestamp)
case .strct:
return .success(org_apache_arrow_flatbuf_Type_.struct_)
default:
@@ -103,6 +105,32 @@ func toFBType( // swiftlint:disable:this
cyclomatic_complexity function_body_len
}
return .failure(.invalid("Unable to case to Time64"))
+ case .timestamp:
+ if let timestampType = arrowType as? ArrowTypeTimestamp {
+ let startOffset =
org_apache_arrow_flatbuf_Timestamp.startTimestamp(&fbb)
+
+ let fbUnit: org_apache_arrow_flatbuf_TimeUnit
+ switch timestampType.unit {
+ case .seconds:
+ fbUnit = .second
+ case .milliseconds:
+ fbUnit = .millisecond
+ case .microseconds:
+ fbUnit = .microsecond
+ case .nanoseconds:
+ fbUnit = .nanosecond
+ }
+ org_apache_arrow_flatbuf_Timestamp.add(unit: fbUnit, &fbb)
+
+ if let timezone = timestampType.timezone {
+ let timezoneOffset = fbb.create(string: timezone)
+ org_apache_arrow_flatbuf_Timestamp.add(timezone:
timezoneOffset, &fbb)
+ }
+
+ return
.success(org_apache_arrow_flatbuf_Timestamp.endTimestamp(&fbb, start:
startOffset))
+ }
+
+ return .failure(.invalid("Unable to cast to Timestamp"))
case .strct:
let startOffset = org_apache_arrow_flatbuf_Struct_.startStruct_(&fbb)
return .success(org_apache_arrow_flatbuf_Struct_.endStruct_(&fbb,
start: startOffset))
diff --git a/Arrow/Sources/Arrow/ProtoUtil.swift
b/Arrow/Sources/Arrow/ProtoUtil.swift
index 88cfb0b..e91580e 100644
--- a/Arrow/Sources/Arrow/ProtoUtil.swift
+++ b/Arrow/Sources/Arrow/ProtoUtil.swift
@@ -64,6 +64,22 @@ func fromProto( // swiftlint:disable:this
cyclomatic_complexity function_body_le
let arrowUnit: ArrowTime64Unit = timeType.unit == .microsecond ?
.microseconds : .nanoseconds
arrowType = ArrowTypeTime64(arrowUnit)
}
+ case .timestamp:
+ let timestampType = field.type(type:
org_apache_arrow_flatbuf_Timestamp.self)!
+ let arrowUnit: ArrowTimestampUnit
+ switch timestampType.unit {
+ case .second:
+ arrowUnit = .seconds
+ case .millisecond:
+ arrowUnit = .milliseconds
+ case .microsecond:
+ arrowUnit = .microseconds
+ case .nanosecond:
+ arrowUnit = .nanoseconds
+ }
+
+ let timezone = timestampType.timezone
+ arrowType = ArrowTypeTimestamp(arrowUnit, timezone: timezone?.isEmpty
== true ? nil : timezone)
case .struct_:
var children = [ArrowField]()
for index in 0..<field.childrenCount {
diff --git a/Arrow/Tests/ArrowTests/ArrayTests.swift
b/Arrow/Tests/ArrowTests/ArrayTests.swift
index d0d7064..c7142c5 100644
--- a/Arrow/Tests/ArrowTests/ArrayTests.swift
+++ b/Arrow/Tests/ArrowTests/ArrayTests.swift
@@ -212,6 +212,76 @@ final class ArrayTests: XCTestCase { //
swiftlint:disable:this type_body_length
XCTAssertEqual(microArray[2], 987654321)
}
+ func testTimestampArray() throws {
+ // Test timestamp with seconds unit
+ let secBuilder = try
ArrowArrayBuilders.loadTimestampArrayBuilder(.seconds, timezone: nil)
+ secBuilder.append(1609459200) // 2021-01-01 00:00:00
+ secBuilder.append(1609545600) // 2021-01-02 00:00:00
+ secBuilder.append(nil)
+ XCTAssertEqual(secBuilder.nullCount, 1)
+ XCTAssertEqual(secBuilder.length, 3)
+ XCTAssertEqual(secBuilder.capacity, 264)
+ let secArray = try secBuilder.finish()
+ let secType = secArray.arrowData.type as! ArrowTypeTimestamp //
swiftlint:disable:this force_cast
+ XCTAssertEqual(secType.unit, .seconds)
+ XCTAssertNil(secType.timezone)
+ XCTAssertEqual(secArray.length, 3)
+ XCTAssertEqual(secArray[0], 1609459200)
+ XCTAssertEqual(secArray[1], 1609545600)
+ XCTAssertNil(secArray[2])
+
+ // Test timestamp with milliseconds unit and timezone America/New_York
+ let msBuilder = try
ArrowArrayBuilders.loadTimestampArrayBuilder(.milliseconds, timezone:
"America/New_York")
+ msBuilder.append(1609459200000) // 2021-01-01 00:00:00.000
+ msBuilder.append(nil)
+ msBuilder.append(1609545600000) // 2021-01-02 00:00:00.000
+ XCTAssertEqual(msBuilder.nullCount, 1)
+ XCTAssertEqual(msBuilder.length, 3)
+ XCTAssertEqual(msBuilder.capacity, 264)
+ let msArray = try msBuilder.finish()
+ let msType = msArray.arrowData.type as! ArrowTypeTimestamp //
swiftlint:disable:this force_cast
+ XCTAssertEqual(msType.unit, .milliseconds)
+ XCTAssertEqual(msType.timezone, "America/New_York")
+ XCTAssertEqual(msArray.length, 3)
+ XCTAssertEqual(msArray[0], 1609459200000)
+ XCTAssertNil(msArray[1])
+ XCTAssertEqual(msArray[2], 1609545600000)
+
+ // Test timestamp with microseconds unit and timezone UTC
+ let usBuilder = try
ArrowArrayBuilders.loadTimestampArrayBuilder(.microseconds, timezone: "UTC")
+ usBuilder.append(1609459200000000) // 2021-01-01 00:00:00.000000
+ usBuilder.append(1609545600000000) // 2021-01-02 00:00:00.000000
+ usBuilder.append(1609632000000000) // 2021-01-03 00:00:00.000000
+ XCTAssertEqual(usBuilder.nullCount, 0)
+ XCTAssertEqual(usBuilder.length, 3)
+ XCTAssertEqual(usBuilder.capacity, 264)
+ let usArray = try usBuilder.finish()
+ let usType = usArray.arrowData.type as! ArrowTypeTimestamp //
swiftlint:disable:this force_cast
+ XCTAssertEqual(usType.unit, .microseconds)
+ XCTAssertEqual(usType.timezone, "UTC")
+ XCTAssertEqual(usArray.length, 3)
+ XCTAssertEqual(usArray[0], 1609459200000000)
+ XCTAssertEqual(usArray[1], 1609545600000000)
+ XCTAssertEqual(usArray[2], 1609632000000000)
+
+ // Test timestamp with nanoseconds unit
+ let nsBuilder = try
ArrowArrayBuilders.loadTimestampArrayBuilder(.nanoseconds, timezone: nil)
+ nsBuilder.append(nil)
+ nsBuilder.append(1609459200000000000) // 2021-01-01 00:00:00.000000000
+ nsBuilder.append(1609545600000000000) // 2021-01-02 00:00:00.000000000
+ XCTAssertEqual(nsBuilder.nullCount, 1)
+ XCTAssertEqual(nsBuilder.length, 3)
+ XCTAssertEqual(nsBuilder.capacity, 264)
+ let nsArray = try nsBuilder.finish()
+ let nsType = nsArray.arrowData.type as! ArrowTypeTimestamp //
swiftlint:disable:this force_cast
+ XCTAssertEqual(nsType.unit, .nanoseconds)
+ XCTAssertNil(nsType.timezone)
+ XCTAssertEqual(nsArray.length, 3)
+ XCTAssertNil(nsArray[0])
+ XCTAssertEqual(nsArray[1], 1609459200000000000)
+ XCTAssertEqual(nsArray[2], 1609545600000000000)
+ }
+
func testStructArray() throws { // swiftlint:disable:this
function_body_length
class StructTest {
var fieldBool: Bool = false
diff --git a/Arrow/Tests/ArrowTests/CDataTests.swift
b/Arrow/Tests/ArrowTests/CDataTests.swift
index 2344b23..e48ebd0 100644
--- a/Arrow/Tests/ArrowTests/CDataTests.swift
+++ b/Arrow/Tests/ArrowTests/CDataTests.swift
@@ -43,7 +43,11 @@ final class CDataTests: XCTestCase {
.addField("colTime64", type: ArrowType(ArrowType.ArrowTime64),
isNullable: false)
.addField("colTime64u", type: ArrowTypeTime64(.microseconds),
isNullable: false)
.addField("colTime64n", type: ArrowTypeTime64(.nanoseconds),
isNullable: false)
- .addField("colTime64", type: ArrowType(ArrowType.ArrowTime64),
isNullable: false)
+ .addField("colTimestamp", type:
ArrowType(ArrowType.ArrowTimestamp), isNullable: false)
+ .addField("colTimestampts", type: ArrowTypeTimestamp(.seconds),
isNullable: false)
+ .addField("colTimestamptm", type:
ArrowTypeTimestamp(.milliseconds), isNullable: false)
+ .addField("colTimestamptu", type:
ArrowTypeTimestamp(.microseconds), isNullable: false)
+ .addField("colTimestamptn", type:
ArrowTypeTimestamp(.nanoseconds), isNullable: false)
.addField("colFloat", type: ArrowType(ArrowType.ArrowFloat),
isNullable: false)
.addField("colDouble", type: ArrowType(ArrowType.ArrowDouble),
isNullable: false)
.finish()