Compare commits
7 Commits
entgo/v1.1
...
entgo/v1.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce04468424 | ||
|
|
d1418caf84 | ||
|
|
f73f016ec5 | ||
|
|
d549d305ae | ||
|
|
23dcad60a3 | ||
|
|
fa7ae4f876 | ||
|
|
9f6a4eba80 |
@@ -63,16 +63,6 @@ var ops = [...]string{
|
|||||||
FilterSearch: "search",
|
FilterSearch: "search",
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasOperations(str string) bool {
|
|
||||||
str = strings.ToLower(str)
|
|
||||||
for _, item := range ops {
|
|
||||||
if str == item {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type DatePart int
|
type DatePart int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -109,6 +99,38 @@ var dateParts = [...]string{
|
|||||||
DatePartMicrosecond: "microsecond",
|
DatePartMicrosecond: "microsecond",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
QueryDelimiter = "__" // 分隔符
|
||||||
|
JsonFieldDelimiter = "." // JSONB字段分隔符
|
||||||
|
)
|
||||||
|
|
||||||
|
// splitQueryKey 分割查询键
|
||||||
|
func splitQueryKey(key string) []string {
|
||||||
|
return strings.Split(key, QueryDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitJsonFieldKey 分割JSON字段键
|
||||||
|
func splitJsonFieldKey(key string) []string {
|
||||||
|
return strings.Split(key, JsonFieldDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// isJsonFieldKey 是否为JSON字段键
|
||||||
|
func isJsonFieldKey(key string) bool {
|
||||||
|
return strings.Contains(key, JsonFieldDelimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasOperations 是否有操作
|
||||||
|
func hasOperations(str string) bool {
|
||||||
|
str = strings.ToLower(str)
|
||||||
|
for _, item := range ops {
|
||||||
|
if str == item {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasDatePart 是否有日期部分
|
||||||
func hasDatePart(str string) bool {
|
func hasDatePart(str string) bool {
|
||||||
str = strings.ToLower(str)
|
str = strings.ToLower(str)
|
||||||
for _, item := range dateParts {
|
for _, item := range dateParts {
|
||||||
@@ -119,6 +141,32 @@ func hasDatePart(str string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildFilterSelector 构建过滤选择器
|
||||||
|
func BuildFilterSelector(andFilterJsonString, orFilterJsonString string) (error, []func(s *sql.Selector)) {
|
||||||
|
var err error
|
||||||
|
var queryConditions []func(s *sql.Selector)
|
||||||
|
|
||||||
|
var andSelector func(s *sql.Selector)
|
||||||
|
err, andSelector = QueryCommandToWhereConditions(andFilterJsonString, false)
|
||||||
|
if err != nil {
|
||||||
|
return err, nil
|
||||||
|
}
|
||||||
|
if andSelector != nil {
|
||||||
|
queryConditions = append(queryConditions, andSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
var orSelector func(s *sql.Selector)
|
||||||
|
err, orSelector = QueryCommandToWhereConditions(orFilterJsonString, true)
|
||||||
|
if err != nil {
|
||||||
|
return err, nil
|
||||||
|
}
|
||||||
|
if orSelector != nil {
|
||||||
|
queryConditions = append(queryConditions, orSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, queryConditions
|
||||||
|
}
|
||||||
|
|
||||||
// QueryCommandToWhereConditions 查询命令转换为选择条件
|
// QueryCommandToWhereConditions 查询命令转换为选择条件
|
||||||
func QueryCommandToWhereConditions(strJson string, isOr bool) (error, func(s *sql.Selector)) {
|
func QueryCommandToWhereConditions(strJson string, isOr bool) (error, func(s *sql.Selector)) {
|
||||||
if len(strJson) == 0 {
|
if len(strJson) == 0 {
|
||||||
@@ -150,14 +198,15 @@ func QueryCommandToWhereConditions(strJson string, isOr bool) (error, func(s *sq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processQueryMap 处理查询映射表
|
||||||
func processQueryMap(s *sql.Selector, queryMap map[string]string) []*sql.Predicate {
|
func processQueryMap(s *sql.Selector, queryMap map[string]string) []*sql.Predicate {
|
||||||
var ps []*sql.Predicate
|
var ps []*sql.Predicate
|
||||||
for k, v := range queryMap {
|
for k, v := range queryMap {
|
||||||
key := stringcase.ToSnakeCase(k)
|
key := stringcase.ToSnakeCase(k)
|
||||||
|
|
||||||
keys := strings.Split(key, "__")
|
keys := splitQueryKey(key)
|
||||||
|
|
||||||
if cond := oneFieldFilter(s, keys, v); cond != nil {
|
if cond := makeFieldFilter(s, keys, v); cond != nil {
|
||||||
ps = append(ps, cond)
|
ps = append(ps, cond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,32 +214,8 @@ func processQueryMap(s *sql.Selector, queryMap map[string]string) []*sql.Predica
|
|||||||
return ps
|
return ps
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildFilterSelector(andFilterJsonString, orFilterJsonString string) (error, []func(s *sql.Selector)) {
|
// makeFieldFilter 构建一个字段过滤器
|
||||||
var err error
|
func makeFieldFilter(s *sql.Selector, keys []string, value string) *sql.Predicate {
|
||||||
var queryConditions []func(s *sql.Selector)
|
|
||||||
|
|
||||||
var andSelector func(s *sql.Selector)
|
|
||||||
err, andSelector = QueryCommandToWhereConditions(andFilterJsonString, false)
|
|
||||||
if err != nil {
|
|
||||||
return err, nil
|
|
||||||
}
|
|
||||||
if andSelector != nil {
|
|
||||||
queryConditions = append(queryConditions, andSelector)
|
|
||||||
}
|
|
||||||
|
|
||||||
var orSelector func(s *sql.Selector)
|
|
||||||
err, orSelector = QueryCommandToWhereConditions(orFilterJsonString, true)
|
|
||||||
if err != nil {
|
|
||||||
return err, nil
|
|
||||||
}
|
|
||||||
if orSelector != nil {
|
|
||||||
queryConditions = append(queryConditions, orSelector)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, queryConditions
|
|
||||||
}
|
|
||||||
|
|
||||||
func oneFieldFilter(s *sql.Selector, keys []string, value string) *sql.Predicate {
|
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -207,6 +232,14 @@ func oneFieldFilter(s *sql.Selector, keys []string, value string) *sql.Predicate
|
|||||||
|
|
||||||
switch len(keys) {
|
switch len(keys) {
|
||||||
case 1:
|
case 1:
|
||||||
|
if isJsonFieldKey(field) {
|
||||||
|
jsonFields := splitJsonFieldKey(field)
|
||||||
|
if len(jsonFields) != 2 {
|
||||||
|
return filterEqual(s, p, field, value)
|
||||||
|
}
|
||||||
|
value = "'" + value + "'"
|
||||||
|
return filterJsonb(s, p, jsonFields[1], jsonFields[0]).EQ("", value)
|
||||||
|
}
|
||||||
return filterEqual(s, p, field, value)
|
return filterEqual(s, p, field, value)
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@@ -215,6 +248,14 @@ func oneFieldFilter(s *sql.Selector, keys []string, value string) *sql.Predicate
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isJsonFieldKey(field) {
|
||||||
|
jsonFields := splitJsonFieldKey(field)
|
||||||
|
if len(jsonFields) == 2 {
|
||||||
|
field = filterJsonbField(s, jsonFields[1], jsonFields[0])
|
||||||
|
value = "'" + value + "'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var cond *sql.Predicate
|
var cond *sql.Predicate
|
||||||
if hasOperations(op) {
|
if hasOperations(op) {
|
||||||
return processOp(s, p, op, field, value)
|
return processOp(s, p, op, field, value)
|
||||||
@@ -241,10 +282,19 @@ func oneFieldFilter(s *sql.Selector, keys []string, value string) *sql.Predicate
|
|||||||
|
|
||||||
//var cond *sql.Predicate
|
//var cond *sql.Predicate
|
||||||
if hasDatePart(op1) {
|
if hasDatePart(op1) {
|
||||||
|
if isJsonFieldKey(field) {
|
||||||
|
jsonFields := splitJsonFieldKey(field)
|
||||||
|
if len(jsonFields) == 2 {
|
||||||
|
field = filterJsonbField(s, jsonFields[1], jsonFields[0])
|
||||||
|
value = "'" + value + "'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
str := filterDatePartField(s, op1, field)
|
str := filterDatePartField(s, op1, field)
|
||||||
if hasOperations(op2) {
|
if hasOperations(op2) {
|
||||||
return processOp(s, p, op2, str, value)
|
return processOp(s, p, op2, str, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
str := filterJsonbField(s, op1, field)
|
str := filterJsonbField(s, op1, field)
|
||||||
@@ -547,6 +597,7 @@ func filterDatePart(s *sql.Selector, p *sql.Predicate, datePart, field string) *
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterDatePartField 日期
|
||||||
func filterDatePartField(s *sql.Selector, datePart, field string) string {
|
func filterDatePartField(s *sql.Selector, datePart, field string) string {
|
||||||
p := sql.P()
|
p := sql.P()
|
||||||
switch s.Builder.Dialect() {
|
switch s.Builder.Dialect() {
|
||||||
@@ -565,12 +616,12 @@ func filterDatePartField(s *sql.Selector, datePart, field string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filterJsonb 提取JSONB字段
|
// filterJsonb 提取JSONB字段
|
||||||
// Postgresql: WHERE ("app_profile"."preferences" -> daily_email) = 'true'
|
// Postgresql: WHERE ("app_profile"."preferences" ->> 'daily_email') = 'true'
|
||||||
func filterJsonb(s *sql.Selector, p *sql.Predicate, jsonbField, field string) *sql.Predicate {
|
func filterJsonb(s *sql.Selector, p *sql.Predicate, jsonbField, field string) *sql.Predicate {
|
||||||
p.Append(func(b *sql.Builder) {
|
p.Append(func(b *sql.Builder) {
|
||||||
switch s.Builder.Dialect() {
|
switch s.Builder.Dialect() {
|
||||||
case dialect.Postgres:
|
case dialect.Postgres:
|
||||||
b.Ident(s.C(field)).WriteString(" -> ").WriteString(jsonbField)
|
b.Ident(s.C(field)).WriteString(" ->> ").WriteString("'" + jsonbField + "'")
|
||||||
//b.Arg(strings.ToLower(value))
|
//b.Arg(strings.ToLower(value))
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -584,11 +635,12 @@ func filterJsonb(s *sql.Selector, p *sql.Predicate, jsonbField, field string) *s
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterJsonbField JSONB字段
|
||||||
func filterJsonbField(s *sql.Selector, jsonbField, field string) string {
|
func filterJsonbField(s *sql.Selector, jsonbField, field string) string {
|
||||||
p := sql.P()
|
p := sql.P()
|
||||||
switch s.Builder.Dialect() {
|
switch s.Builder.Dialect() {
|
||||||
case dialect.Postgres:
|
case dialect.Postgres:
|
||||||
p.Ident(s.C(field)).WriteString(" -> ").WriteString(jsonbField)
|
p.Ident(s.C(field)).WriteString(" ->> ").WriteString("'" + jsonbField + "'")
|
||||||
//b.Arg(strings.ToLower(value))
|
//b.Arg(strings.ToLower(value))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
@@ -681,14 +681,104 @@ func TestFilter(t *testing.T) {
|
|||||||
s.Where(p)
|
s.Where(p)
|
||||||
|
|
||||||
query, args := s.Query()
|
query, args := s.Query()
|
||||||
require.Equal(t, "SELECT * FROM \"app_profile\" WHERE \"app_profile\".\"preferences\" -> daily_email = $1", query)
|
require.Equal(t, "SELECT * FROM \"app_profile\" WHERE \"app_profile\".\"preferences\" ->> 'daily_email' = $1", query)
|
||||||
require.NotEmpty(t, args)
|
require.NotEmpty(t, args)
|
||||||
require.Equal(t, args[0], "true")
|
require.Equal(t, args[0], "true")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterJsonbField(t *testing.T) {
|
func TestFilterJsonbField(t *testing.T) {
|
||||||
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("app_profile"))
|
t.Run("filterJsonbField", func(t *testing.T) {
|
||||||
str := filterJsonbField(s, "daily_email", "preferences")
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("app_profile"))
|
||||||
fmt.Println(str)
|
str := filterJsonbField(s, "daily_email", "preferences")
|
||||||
|
fmt.Println(str)
|
||||||
|
require.Equal(t, str, "\"app_profile\".\"preferences\" ->> 'daily_email'")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterEqual", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("menus"))
|
||||||
|
|
||||||
|
p := sql.P()
|
||||||
|
|
||||||
|
p = makeFieldFilter(s, []string{"meta.title"}, "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `menus` WHERE JSON_EXTRACT(`menus`.`meta`, '$.title') = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "'tom'")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterEqual", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("menus"))
|
||||||
|
|
||||||
|
p := sql.P()
|
||||||
|
|
||||||
|
p = makeFieldFilter(s, []string{"meta.title"}, "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"menus\" WHERE \"menus\".\"meta\" ->> 'title' = $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "'tom'")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterNot", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := sql.P()
|
||||||
|
|
||||||
|
p = makeFieldFilter(s, []string{"meta.title", "not"}, "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE NOT JSON_EXTRACT(`users`.`meta`, '$.title') = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "'tom'")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterNot", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := sql.P()
|
||||||
|
|
||||||
|
p = makeFieldFilter(s, []string{"meta.title", "not"}, "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE NOT \"users\".\"meta\" ->> 'title' = $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "'tom'")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterNot_Date", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := sql.P()
|
||||||
|
|
||||||
|
p = makeFieldFilter(s, []string{"meta.title", "date", "not"}, "2023-01-01")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE NOT DATE(JSON_EXTRACT(`users`.`meta`, '$.title')) = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "'2023-01-01'")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterNot_Date", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := sql.P()
|
||||||
|
|
||||||
|
p = makeFieldFilter(s, []string{"meta.title", "date", "not"}, "2023-01-01")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE NOT EXTRACT('DATE' FROM \"users\".\"meta\" ->> 'title') = $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "'2023-01-01'")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package entgo
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"entgo.io/ent/dialect"
|
"entgo.io/ent/dialect"
|
||||||
@@ -85,11 +84,11 @@ func TestJsonCodec(t *testing.T) {
|
|||||||
func TestSplitQuery(t *testing.T) {
|
func TestSplitQuery(t *testing.T) {
|
||||||
var keys []string
|
var keys []string
|
||||||
|
|
||||||
keys = strings.Split("id", "__")
|
keys = splitQueryKey("id")
|
||||||
assert.Equal(t, len(keys), 1)
|
assert.Equal(t, len(keys), 1)
|
||||||
assert.Equal(t, keys[0], "id")
|
assert.Equal(t, keys[0], "id")
|
||||||
|
|
||||||
keys = strings.Split("id__not", "__")
|
keys = splitQueryKey("id__not")
|
||||||
assert.Equal(t, len(keys), 2)
|
assert.Equal(t, len(keys), 2)
|
||||||
assert.Equal(t, keys[0], "id")
|
assert.Equal(t, keys[0], "id")
|
||||||
assert.Equal(t, keys[1], "not")
|
assert.Equal(t, keys[1], "not")
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func BuildSetNullUpdater(fields []string) func(u *sql.UpdateBuilder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExtractJsonFieldKeyValues 提取json字段的键值对
|
// ExtractJsonFieldKeyValues 提取json字段的键值对
|
||||||
func ExtractJsonFieldKeyValues(msg proto.Message, paths []string) []string {
|
func ExtractJsonFieldKeyValues(msg proto.Message, paths []string, needToSnakeCase bool) []string {
|
||||||
var keyValues []string
|
var keyValues []string
|
||||||
rft := msg.ProtoReflect()
|
rft := msg.ProtoReflect()
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
@@ -46,7 +46,14 @@ func ExtractJsonFieldKeyValues(msg proto.Message, paths []string) []string {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
keyValues = append(keyValues, fmt.Sprintf("'%s'", stringcase.ToSnakeCase(path)))
|
var k string
|
||||||
|
if needToSnakeCase {
|
||||||
|
k = stringcase.ToSnakeCase(path)
|
||||||
|
} else {
|
||||||
|
k = path
|
||||||
|
}
|
||||||
|
|
||||||
|
keyValues = append(keyValues, fmt.Sprintf("'%s'", k))
|
||||||
|
|
||||||
v := rft.Get(fd)
|
v := rft.Get(fd)
|
||||||
switch v.Interface().(type) {
|
switch v.Interface().(type) {
|
||||||
@@ -77,8 +84,8 @@ func SetJsonNullFieldUpdateBuilder(fieldName string, msg proto.Message, paths []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetJsonFieldValueUpdateBuilder 设置json字段的值
|
// SetJsonFieldValueUpdateBuilder 设置json字段的值
|
||||||
func SetJsonFieldValueUpdateBuilder(fieldName string, msg proto.Message, paths []string) func(u *sql.UpdateBuilder) {
|
func SetJsonFieldValueUpdateBuilder(fieldName string, msg proto.Message, paths []string, needToSnakeCase bool) func(u *sql.UpdateBuilder) {
|
||||||
keyValues := ExtractJsonFieldKeyValues(msg, paths)
|
keyValues := ExtractJsonFieldKeyValues(msg, paths, needToSnakeCase)
|
||||||
if len(keyValues) == 0 {
|
if len(keyValues) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
2
tag.bat
2
tag.bat
@@ -3,7 +3,7 @@ git tag v1.1.13
|
|||||||
git tag bank_card/v1.1.3
|
git tag bank_card/v1.1.3
|
||||||
git tag geoip/v1.1.3
|
git tag geoip/v1.1.3
|
||||||
|
|
||||||
git tag entgo/v1.1.17
|
git tag entgo/v1.1.22
|
||||||
git tag gorm/v1.1.3
|
git tag gorm/v1.1.3
|
||||||
|
|
||||||
git push origin --tags
|
git push origin --tags
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
"github.com/tx7do/go-utils/trans"
|
"github.com/tx7do/go-utils/trans"
|
||||||
@@ -132,3 +133,19 @@ func TimeToTimestamppb(tm *time.Time) *timestamppb.Timestamp {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FloatToDurationpb(duration *float64, timePrecision time.Duration) *durationpb.Duration {
|
||||||
|
if duration == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return durationpb.New(time.Duration(*duration) * timePrecision)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DurationpbToFloat(duration *durationpb.Duration, timePrecision time.Duration) *float64 {
|
||||||
|
if duration == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
seconds := duration.AsDuration().Seconds()
|
||||||
|
secondsWithPrecision := seconds / timePrecision.Seconds()
|
||||||
|
return &secondsWithPrecision
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package timeutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|||||||
Reference in New Issue
Block a user