github.com/matrixorigin/matrixone@v0.7.0/pkg/vectorize/timediff/timediff.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package timediff
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/container/types"
    19  )
    20  
    21  type DiffT interface {
    22  	types.Time | types.Datetime
    23  }
    24  
    25  func TimeDiffWithTimeFn[T DiffT](v1, v2 []T, rs []types.Time) error {
    26  	if len(v1) == 1 && len(v2) == 1 {
    27  		for i := 0; i < len(rs); i++ {
    28  			res, err := timeDiff(v1[0], v2[0])
    29  			if err != nil {
    30  				return err
    31  			}
    32  			rs[0] = res
    33  		}
    34  	} else if len(v1) == 1 {
    35  		for i := 0; i < len(rs); i++ {
    36  			res, err := timeDiff(v1[0], v2[i])
    37  			if err != nil {
    38  				return err
    39  			}
    40  			rs[i] = res
    41  		}
    42  	} else if len(v2) == 1 {
    43  		for i := 0; i < len(rs); i++ {
    44  			res, err := timeDiff(v1[i], v2[0])
    45  			if err != nil {
    46  				return err
    47  			}
    48  			rs[i] = res
    49  		}
    50  	} else {
    51  		for i := 0; i < len(rs); i++ {
    52  			res, err := timeDiff(v1[i], v2[i])
    53  			if err != nil {
    54  				return err
    55  			}
    56  			rs[i] = res
    57  		}
    58  	}
    59  	return nil
    60  }
    61  
    62  func timeDiff[T DiffT](v1, v2 T) (types.Time, error) {
    63  	tmpTime := int64(v1 - v2)
    64  	// different sign need to check over flow
    65  	if (int64(v1)>>63)^(int64(v2)>>63) != 0 {
    66  		if (tmpTime>>63)^(int64(v1)>>63) != 0 {
    67  			// overflow
    68  			isNeg := int64(v1) < 0
    69  			return types.TimeFromClock(isNeg, types.MaxHourInTime, 59, 59, 0), nil
    70  		}
    71  	}
    72  
    73  	// same sign don't need to check overflow
    74  	time := types.Time(tmpTime)
    75  	hour, _, _, _, isNeg := time.ClockFormat()
    76  	if !types.ValidTime(uint64(hour), 0, 0) {
    77  		return types.TimeFromClock(isNeg, types.MaxHourInTime, 59, 59, 0), nil
    78  	}
    79  	return time, nil
    80  }