client/utils.go (229 lines of code) (raw):

/* * 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. */ package client import ( "bytes" "encoding/binary" "errors" "fmt" "github.com/apache/iotdb-client-go/common" "github.com/apache/iotdb-client-go/rpc" "strconv" "time" ) const ( DEFAULT_TIME_FORMAT = "default" TIME_PRECISION = "timestamp_precision" MILLISECOND = "ms" MICROSECOND = "us" NANOSECOND = "ns" ) func getTimeFactor(openResp *rpc.TSOpenSessionResp) (int32, error) { if !openResp.IsSetConfiguration() { return 1_000, nil } precision, exists := openResp.GetConfiguration()[TIME_PRECISION] if !exists { return 1_000, nil } switch precision { case MILLISECOND: return 1_000, nil case MICROSECOND: return 1_000_000, nil case NANOSECOND: return 1_000_000_000, nil default: return 0, fmt.Errorf("unknown time precision: %v", precision) } } func getTimePrecision(timeFactor int32) (string, error) { switch timeFactor { case 1_000: return MILLISECOND, nil case 1_000_000: return MICROSECOND, nil case 1_000_000_000: return NANOSECOND, nil default: return "", fmt.Errorf("unknown time factor: %v", timeFactor) } } func formatDatetime(timeFormat, timePrecision string, timestamp int64, zone *time.Location) string { switch timeFormat { case "long", "number": return strconv.FormatInt(timestamp, 10) case "default", "iso8601": return parseLongToDateWithPrecision(timestamp, zone, timePrecision) default: sec := timestamp / 1000 nsec := (timestamp % 1000) * int64(time.Millisecond) t := time.Unix(sec, nsec).In(zone) return t.Format(timeFormat) } } func getMilliSecond(timeValue int64, timeFactor int32) int64 { return (timeValue / int64(timeFactor)) * 1_000 } func getNanoSecond(timeValue int64, timeFactor int32) int { return int((timeValue % int64(timeFactor)) * (1_000_000_000 / int64(timeFactor))) } func convertToTimestamp(timeValue int64, timeFactor int32) time.Time { millis := getMilliSecond(timeValue, timeFactor) nanos := getNanoSecond(timeValue, timeFactor) return time.Unix(millis/1e3, (millis%1e3)*1e6).Add(time.Duration(nanos) * time.Nanosecond) } func parseLongToDateWithPrecision(timestamp int64, zone *time.Location, precision string) string { var divisor int64 var digits int switch precision { case MILLISECOND: divisor = 1000 digits = 3 case MICROSECOND: divisor = 1_000_000 digits = 6 case NANOSECOND: divisor = 1_000_000_000 digits = 9 default: return "" } quotient := timestamp / divisor remainder := timestamp % divisor if timestamp < 0 && remainder != 0 { quotient-- remainder += divisor } t := time.Unix(quotient, 0).In(zone) year, month, day := t.Date() hour, min, sec := t.Clock() _, offset := t.Zone() offsetSeconds := offset sign := "+" if offsetSeconds < 0 { sign = "-" offsetSeconds = -offsetSeconds } hours := offsetSeconds / 3600 minutes := (offsetSeconds % 3600) / 60 zoneOffset := fmt.Sprintf("%s%02d:%02d", sign, hours, minutes) if offset == 0 { zoneOffset = "Z" } formatStr := fmt.Sprintf("%%0%dd", digits) fraction := fmt.Sprintf(formatStr, remainder) isoStr := fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02d.%s%s", year, month, day, hour, min, sec, fraction, zoneOffset) return isoStr } func int32ToString(n int32) string { return strconv.Itoa(int(n)) } func int64ToString(n int64) string { return strconv.FormatInt(n, 10) } func float32ToString(val float32) string { return strconv.FormatFloat(float64(val), 'f', -1, 32) } func float64ToString(val float64) string { return strconv.FormatFloat(val, 'f', -1, 64) } func int32ToBytes(n int32) []byte { bytesBuffer := bytes.NewBuffer([]byte{}) binary.Write(bytesBuffer, binary.BigEndian, n) return bytesBuffer.Bytes() } func int64ToBytes(n int64) []byte { bytesBuffer := bytes.NewBuffer([]byte{}) binary.Write(bytesBuffer, binary.BigEndian, n) return bytesBuffer.Bytes() } func bytesToInt32(bys []byte) int32 { bytesBuffer := bytes.NewBuffer(bys) var data int32 binary.Read(bytesBuffer, binary.BigEndian, &data) return data } func bytesToInt64(bys []byte) int64 { bytesBuffer := bytes.NewBuffer(bys) var data int64 binary.Read(bytesBuffer, binary.BigEndian, &data) return data } func bytesToHexString(input []byte) string { hexString := "0x" if input != nil { for _, b := range input { hexString += fmt.Sprintf("%02x", b) } } return hexString } func DateToInt32(localDate time.Time) (int32, error) { if localDate.IsZero() { return 0, errors.New("date expression is null or empty") } year := localDate.Year() if year < 1000 || year > 9999 { return 0, errors.New("year must be between 1000 and 9999") } // Convert to YYYY/MM/DD format result := year*10000 + int(localDate.Month())*100 + localDate.Day() return int32(result), nil } func Int32ToDate(val int32) (time.Time, error) { date := int(val) year := date / 10000 month := (date / 100) % 100 day := date % 100 localDate := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) if localDate.Year() != year || int(localDate.Month()) != month || localDate.Day() != day { return time.Time{}, errors.New("invalid date format") } return localDate, nil } func bytesToDate(bys []byte) (time.Time, error) { return Int32ToDate(bytesToInt32(bys)) } func verifySuccesses(statuses []*common.TSStatus) error { buff := bytes.Buffer{} for _, status := range statuses { if status.Code != SuccessStatus && status.Code != RedirectionRecommend { buff.WriteString(*status.Message + ";") } } errMsg := buff.String() if len(errMsg) > 0 { return NewBatchError(statuses) } return nil } func VerifySuccess(status *common.TSStatus) error { if status.Code == RedirectionRecommend { return nil } if status.Code == MultipleError { if err := verifySuccesses(status.GetSubStatus()); err != nil { return err } return nil } if status.Code != SuccessStatus { if status.Message != nil { return fmt.Errorf("error code: %d, message: %v", status.Code, *status.Message) } else { return fmt.Errorf("error code: %d", status.Code) } } return nil } type Binary struct { values []byte } func NewBinary(v []byte) *Binary { return &Binary{v} } func (b *Binary) GetStringValue() string { return string(b.values) } func (b *Binary) GetValues() []byte { return b.values }