Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-37231: [MATLAB] Add arrow.type.Time32Type class and arrow.time32 construction function #37250

Merged
merged 13 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions matlab/src/cpp/arrow/matlab/proxy/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "arrow/matlab/type/proxy/primitive_ctype.h"
#include "arrow/matlab/type/proxy/string_type.h"
#include "arrow/matlab/type/proxy/timestamp_type.h"
#include "arrow/matlab/type/proxy/time32_type.h"
#include "arrow/matlab/type/proxy/field.h"
#include "arrow/matlab/io/feather/proxy/writer.h"
#include "arrow/matlab/io/feather/proxy/reader.h"
Expand Down Expand Up @@ -63,6 +64,7 @@ libmexclass::proxy::MakeResult Factory::make_proxy(const ClassName& class_name,
REGISTER_PROXY(arrow.type.proxy.BooleanType , arrow::matlab::type::proxy::PrimitiveCType<bool>);
REGISTER_PROXY(arrow.type.proxy.StringType , arrow::matlab::type::proxy::StringType);
REGISTER_PROXY(arrow.type.proxy.TimestampType , arrow::matlab::type::proxy::TimestampType);
REGISTER_PROXY(arrow.type.proxy.Time32Type , arrow::matlab::type::proxy::Time32Type);
REGISTER_PROXY(arrow.io.feather.proxy.Writer , arrow::matlab::io::feather::proxy::Writer);
REGISTER_PROXY(arrow.io.feather.proxy.Reader , arrow::matlab::io::feather::proxy::Reader);

Expand Down
60 changes: 60 additions & 0 deletions matlab/src/cpp/arrow/matlab/type/proxy/time32_type.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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.

#include "arrow/matlab/type/proxy/time32_type.h"
#include "arrow/matlab/type/time_unit.h"
#include "arrow/matlab/error/error.h"
#include "arrow/util/utf8.h"

namespace arrow::matlab::type::proxy {

Time32Type::Time32Type(std::shared_ptr<arrow::Time32Type> time32_type) : FixedWidthType(std::move(time32_type)) {
REGISTER_METHOD(Time32Type, getTimeUnit);
}

libmexclass::proxy::MakeResult Time32Type::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {
namespace mda = ::matlab::data;

using Time32TypeProxy = arrow::matlab::type::proxy::Time32Type;

mda::StructArray opts = constructor_arguments[0];

const mda::StringArray timeunit_mda = opts[0]["TimeUnit"];

// extract the time unit
const std::u16string& utf16_timeunit = timeunit_mda[0];
MATLAB_ASSIGN_OR_ERROR(const auto timeunit,
arrow::matlab::type::timeUnitFromString(utf16_timeunit),
error::UKNOWN_TIME_UNIT_ERROR_ID);

auto type = arrow::time32(timeunit);
auto time_type = std::static_pointer_cast<arrow::Time32Type>(type);
return std::make_shared<Time32TypeProxy>(std::move(time_type));
}

void Time32Type::getTimeUnit(libmexclass::proxy::method::Context& context) {
namespace mda = ::matlab::data;
mda::ArrayFactory factory;

auto time32_type = std::static_pointer_cast<arrow::Time32Type>(data_type);
const auto timeunit = time32_type->unit();
// Cast to uint8_t since there are only four supported TimeUnit enumeration values:
// Nanosecond, Microsecond, Millisecond, Second
auto timeunit_mda = factory.createScalar(static_cast<uint8_t>(timeunit));
context.outputs[0] = timeunit_mda;
}
}
39 changes: 39 additions & 0 deletions matlab/src/cpp/arrow/matlab/type/proxy/time32_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.

#pragma once

#include "arrow/matlab/type/proxy/fixed_width_type.h"
#include "arrow/type_traits.h"

namespace arrow::matlab::type::proxy {

class Time32Type : public arrow::matlab::type::proxy::FixedWidthType {

public:
Time32Type(std::shared_ptr<arrow::Time32Type> time32_type);

~Time32Type() {}

static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments);

protected:
void getTimeUnit(libmexclass::proxy::method::Context& context);
};

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
%TIMEUNIT Validates whether the given arrow.type.TimeUnit enumeration
% value is supported for the specified temporal type.

% 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.
function timeUnit(temporalType, timeUnit)
arguments
temporalType (1,1) string {mustBeMember(temporalType, ["Time32", "Time64"])}
timeUnit (1,1) arrow.type.TimeUnit
end
import arrow.type.TimeUnit

switch temporalType
case "Time32"
if ~(timeUnit == TimeUnit.Second || timeUnit == TimeUnit.Millisecond)
errid = "arrow:validate:temporal:UnsupportedTime32TimeUnit";
msg = "Supported TimeUnit values for Time32Type are ""Second"" and ""Millisecond"".";
error(errid, msg);
end
case "Time64"
if ~(timeUnit == TimeUnit.Microsecond || timeUnit == TimeUnit.Nanosecond)
errid = "arrow:validate:temporal:UnsupportedTime64TimeUnit";
msg = "Supported TimeUnit values for Time64Type are ""Microsecond"" and ""Nanosecond"".";
error(errid, msg);
end
end
end
1 change: 1 addition & 0 deletions matlab/src/matlab/+arrow/+type/ID.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@
% Date32 (16)
% Date64 (17)
Timestamp (18)
Time32 (19)
end
end
38 changes: 38 additions & 0 deletions matlab/src/matlab/+arrow/+type/Time32Type.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
%TIME32TYPE Type class for time32 data.

% 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.

classdef Time32Type < arrow.type.TemporalType

methods
function obj = Time32Type(proxy)
arguments
proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, "arrow.type.proxy.Time32Type")}
end
import arrow.internal.proxy.validate

obj@arrow.type.TemporalType(proxy);
end
end

methods (Access=protected)
function group = getPropertyGroups(~)
targets = ["ID" "TimeUnit"];
group = matlab.mixin.util.PropertyGroup(targets);
end
end

end
25 changes: 25 additions & 0 deletions matlab/src/matlab/+arrow/time32.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
% 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.

function type = time32(opts)
%TIME32 Creates an arrow.type.Time32Type object
arguments
opts.TimeUnit(1, 1) arrow.type.TimeUnit {timeUnit("Time32", opts.TimeUnit)} = arrow.type.TimeUnit.Second
end
import arrow.internal.validate.temporal.timeUnit
args = struct(TimeUnit=string(opts.TimeUnit));
proxy = arrow.internal.proxy.create("arrow.type.proxy.Time32Type", args);
type = arrow.type.Time32Type(proxy);
end
133 changes: 133 additions & 0 deletions matlab/test/arrow/internal/validate/temporal/tTimeUnit.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
%TTIMEUNIT Unit tests for arrow.internal.validate.temporal.timeUnit.

% 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.

classdef tTimeUnit < matlab.unittest.TestCase

methods(Test)

function ErrorIfUnsupportedTemporalType(testCase)
import arrow.internal.validate.temporal.timeUnit
import arrow.type.TimeUnit

temporalType = "abc";
unit = TimeUnit.Second;
fcn = @() timeUnit(temporalType, unit);
errid = "MATLAB:validators:mustBeMember";
testCase.verifyError(fcn, errid);

temporalType = 123;
unit = TimeUnit.Second;
fcn = @() timeUnit(temporalType, unit);
errid = "MATLAB:validators:mustBeMember";
testCase.verifyError(fcn, errid);

temporalType = [1, 2, 3];
unit = TimeUnit.Second;
fcn = @() timeUnit(temporalType, unit);
errid = "MATLAB:validation:IncompatibleSize";
testCase.verifyError(fcn, errid);
end

function ErrorIfUnsupportedTimeUnitType(testCase)
import arrow.internal.validate.temporal.timeUnit
import arrow.type.TimeUnit

temporalType = "Time32";
unit = "abc";
fcn = @() timeUnit(temporalType, unit);
errid = "MATLAB:validation:UnableToConvert";
testCase.verifyError(fcn, errid);

temporalType = "Time32";
unit = 123;
fcn = @() timeUnit(temporalType, unit);
errid = "MATLAB:validation:UnableToConvert";
testCase.verifyError(fcn, errid);

temporalType = "Time32";
unit = [1, 2, 3];
fcn = @() timeUnit(temporalType, unit);
errid = "MATLAB:validation:IncompatibleSize";
testCase.verifyError(fcn, errid);
end

function SupportedTime32TimeUnit(testCase)
import arrow.internal.validate.temporal.timeUnit
import arrow.type.TimeUnit

temporalType = "Time32";

unit = TimeUnit.Second;
fcn = @() timeUnit(temporalType, unit);
testCase.verifyWarningFree(fcn);

unit = TimeUnit.Millisecond;
fcn = @() timeUnit(temporalType, unit);
testCase.verifyWarningFree(fcn);
end

function SupportedTime64TimeUnit(testCase)
import arrow.internal.validate.temporal.timeUnit
import arrow.type.TimeUnit

temporalType = "Time64";

unit = TimeUnit.Microsecond;
fcn = @() timeUnit(temporalType, unit);
testCase.verifyWarningFree(fcn);

unit = TimeUnit.Nanosecond;
fcn = @() timeUnit(temporalType, unit);
testCase.verifyWarningFree(fcn);
end

function UnsupportedTime32TimeUnit(testCase)
import arrow.internal.validate.temporal.timeUnit
import arrow.type.TimeUnit

temporalType = "Time32";

unit = TimeUnit.Microsecond;
fcn = @() timeUnit(temporalType, unit);
errorID = "arrow:validate:temporal:UnsupportedTime32TimeUnit";
testCase.verifyError(fcn, errorID);

unit = TimeUnit.Nanosecond;
fcn = @() timeUnit(temporalType, unit);
errorID = "arrow:validate:temporal:UnsupportedTime32TimeUnit";
testCase.verifyError(fcn, errorID);
end

function UnsupportedTime64TimeUnit(testCase)
import arrow.internal.validate.temporal.timeUnit
import arrow.type.TimeUnit

temporalType = "Time64";

unit = TimeUnit.Second;
fcn = @() timeUnit(temporalType, unit);
errorID = "arrow:validate:temporal:UnsupportedTime64TimeUnit";
testCase.verifyError(fcn, errorID);

unit = TimeUnit.Millisecond;
fcn = @() timeUnit(temporalType, unit);
errorID = "arrow:validate:temporal:UnsupportedTime64TimeUnit";
testCase.verifyError(fcn, errorID);
end

end
end
29 changes: 22 additions & 7 deletions matlab/test/arrow/type/tID.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,29 @@ function verifyOnMatlabPath(tc)
function CastToUInt64(testCase)
import arrow.type.ID

typeIDs = [ID.Boolean, ID.UInt8, ID.Int8, ID.UInt16, ...
ID.Int16, ID.UInt32, ID.Int32, ID.UInt64, ...
ID.Int64, ID.Float32, ID.Float64];
typeIDs = dictionary( ...
ID.Boolean, 1, ...
ID.UInt8, 2, ...
ID.Int8, 3, ...
ID.UInt16, 4, ...
ID.Int16, 5, ...
ID.UInt32, 6, ...
ID.Int32, 7, ...
ID.UInt64, 8, ...
ID.Int64, 9, ...
ID.Float32, 11, ...
ID.Float64, 12, ...
ID.String, 13, ...
ID.Timestamp, 18, ...
ID.Time32, 19 ...
);

expectedValues = uint64([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12]);
for ii = 1:numel(typeIDs)
actualValue = uint64(typeIDs(ii));
expectedValue = expectedValues(ii);
enumValues = typeIDs.keys();
uint64Values = uint64(typeIDs.values());

for ii = 1:numel(enumValues)
actualValue = uint64(enumValues(ii));
expectedValue = uint64Values(ii);
testCase.verifyEqual(actualValue, expectedValue);
end
end
Expand Down
Loading