github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/pkg/helper/timestamp.go (about)

     1  package helper
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	consts "github.com/easysoft/zendata/internal/pkg/const"
    11  	"github.com/easysoft/zendata/internal/pkg/domain"
    12  	stringUtils "github.com/easysoft/zendata/pkg/utils/string"
    13  	"github.com/easysoft/zendata/pkg/utils/vari"
    14  	"github.com/oklog/ulid/v2"
    15  )
    16  
    17  func CreateTimestampField(field *domain.DefField, fieldWithValue *domain.FieldWithValues) {
    18  	ConvertTmFormat(field)
    19  
    20  	fieldWithValue.Field = field.Field
    21  
    22  	rang := strings.Trim(strings.TrimSpace(field.Range), ",")
    23  	rangeSections := strings.Split(rang, ",")
    24  
    25  	values := make([]interface{}, 0)
    26  	for _, section := range rangeSections {
    27  		CreateTimestampSectionValue(section, &values)
    28  	}
    29  
    30  	if len(values) == 0 {
    31  		values = append(values, "N/A")
    32  	}
    33  
    34  	fieldWithValue.Values = values
    35  }
    36  
    37  func CreateUlidField(field *domain.DefField, fieldWithValue *domain.FieldWithValues) {
    38  	count := 0
    39  
    40  	t := time.Unix(1000000, 0)
    41  	entropy := ulid.Monotonic(rand.New(rand.NewSource(t.UnixNano())), 0)
    42  
    43  	for true {
    44  		val := ulid.MustNew(ulid.Timestamp(t), entropy).String()
    45  		fieldWithValue.Values = append(fieldWithValue.Values, val)
    46  
    47  		count++
    48  		if count >= consts.MaxNumb || count > vari.GlobalVars.Total {
    49  			break
    50  		}
    51  	}
    52  }
    53  
    54  func ConvertTmFormat(field *domain.DefField) { // to 2006-01-02 15:04:05
    55  	format := field.Format
    56  
    57  	if strings.Index(format, "YYYY") > -1 {
    58  		format = strings.Replace(format, "YYYY", "2006", 1)
    59  	} else {
    60  		format = strings.Replace(format, "YY", "06", 1)
    61  	}
    62  
    63  	format = strings.Replace(format, "MM", "01", 1)
    64  	format = strings.Replace(format, "DD", "02", 1)
    65  	format = strings.Replace(format, "hh", "15", 1)
    66  	format = strings.Replace(format, "mm", "04", 1)
    67  	format = strings.Replace(format, "ss", "05", 1)
    68  
    69  	field.Format = format
    70  }
    71  
    72  func CreateTimestampSectionValue(section string, values *[]interface{}) {
    73  	desc, step, unit := parseTsSection(section)
    74  	start, end := parseTsDesc(desc)
    75  
    76  	if (step > 0 && start > end) || (step < 0 && start < end) {
    77  		step *= -1
    78  	}
    79  
    80  	// get index numbers for data retrieve
    81  	numbs := GenerateTimeItems(start, end, step, unit, 1, "")
    82  
    83  	// generate data by index
    84  	index := 0
    85  	for _, numb := range numbs {
    86  		if index >= consts.MaxNumb {
    87  			break
    88  		}
    89  
    90  		*values = append(*values, numb)
    91  		index = index + 1
    92  	}
    93  }
    94  
    95  func parseTsSection(section string) (desc string, step int, unit string) {
    96  	section = strings.Trim(strings.TrimSpace(section), ":")
    97  
    98  	sectionArr := strings.Split(section, ":")
    99  	desc = sectionArr[0]
   100  	if len(sectionArr) > 1 {
   101  		stepStr := sectionArr[1]
   102  		step, unit = parseTsExpr(stepStr)
   103  		if step == 0 {
   104  			step = 1
   105  		}
   106  	}
   107  
   108  	return
   109  }
   110  
   111  func parseTsDesc(desc string) (start, end int64) {
   112  	desc = strings.TrimSpace(desc)
   113  
   114  	if strings.Contains(desc, "today") {
   115  		start, end = getTodayTs()
   116  		return
   117  	}
   118  
   119  	startStr, endStr := splitTmDesc(desc)
   120  
   121  	start = parseTsValue(startStr, true)
   122  	end = parseTsValue(endStr, false)
   123  
   124  	//logUtils.PrintTo(
   125  	//	fmt.Sprintf("From %s to %s",
   126  	//		time.Unix(start, 0).Format("2006-01-02 15:04:05"),
   127  	//		time.Unix(end, 0).Format("2006-01-02 15:04:05")))
   128  
   129  	return
   130  }
   131  
   132  func splitTmDesc(desc string) (start, end string) {
   133  	runeArr := []rune(desc)
   134  
   135  	index := -1
   136  	bracketsOpen := false
   137  	for i := 0; i < len(runeArr); i++ {
   138  		c := runeArr[i]
   139  
   140  		if c == consts.RightBrackets {
   141  			bracketsOpen = false
   142  		} else if c == consts.LeftBrackets {
   143  			bracketsOpen = true
   144  		}
   145  
   146  		str := fmt.Sprintf("%c", c)
   147  		if !bracketsOpen && str == "-" {
   148  			index = i
   149  			break
   150  		}
   151  	}
   152  
   153  	if index == -1 {
   154  		start = desc
   155  	} else if index == 0 {
   156  		end = desc[1:]
   157  	} else if index == len(desc)-1 {
   158  		start = desc[:index]
   159  	} else {
   160  		start = desc[:index]
   161  		end = desc[index+1:]
   162  	}
   163  
   164  	if len(start) > 0 {
   165  		start = strings.TrimPrefix(start, string(consts.LeftBrackets))
   166  		start = strings.TrimSuffix(start, string(consts.RightBrackets))
   167  	}
   168  	if len(end) > 0 {
   169  		end = strings.TrimPrefix(end, string(consts.LeftBrackets))
   170  		end = strings.TrimSuffix(end, string(consts.RightBrackets))
   171  	}
   172  
   173  	return
   174  }
   175  
   176  func parseTsValue(str string, isStart bool) (value int64) {
   177  	str = strings.TrimSpace(str)
   178  
   179  	if strings.HasPrefix(str, "+") || strings.HasPrefix(str, "-") {
   180  		value = time.Now().Unix()
   181  
   182  		value = increment(value, str)
   183  
   184  		return
   185  	}
   186  
   187  	loc, _ := time.LoadLocation("Local")
   188  	tm, err := time.ParseInLocation("20060102 150405", str, loc)
   189  	if err != nil {
   190  		todayStart, todayEnd := getTodayTs()
   191  		if isStart {
   192  			value = todayStart
   193  		} else {
   194  			value = todayEnd
   195  		}
   196  	} else {
   197  		value = tm.Unix()
   198  	}
   199  
   200  	return
   201  }
   202  
   203  func getTodayTs() (start, end int64) {
   204  	now := time.Now()
   205  
   206  	start = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
   207  	end = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()).Unix()
   208  
   209  	return
   210  }
   211  
   212  // parse time expression to number and unit
   213  // example: parseTsExpr("+3w") ->  int(3) and "w"
   214  func parseTsExpr(incrementStr string) (num int, unit string) {
   215  	num = 0
   216  	unit = "s"
   217  	incrementStr = strings.TrimSpace(incrementStr)
   218  	if len(incrementStr) <= 0 {
   219  		return
   220  	}
   221  
   222  	units := []string{"Y", "M", "D", "w", "h", "m", "s"}
   223  
   224  	unit = string(incrementStr[len(incrementStr)-1])
   225  	found, _ := stringUtils.FindInArr(unit, units)
   226  	end := len(incrementStr) - 1
   227  	if !found {
   228  		unit = "s"
   229  		end = len(incrementStr)
   230  	}
   231  
   232  	numStr := incrementStr[:end]
   233  	num, _ = strconv.Atoi(numStr)
   234  	return
   235  }
   236  
   237  func incrementUnit(originalVal int64, incNum int, unit string) (ret int64) {
   238  	ret = originalVal
   239  
   240  	start := time.Unix(ret, 0)
   241  	if incNum == 0 {
   242  		return
   243  	}
   244  	switch unit {
   245  	case "Y":
   246  		start = start.AddDate(incNum, 0, 0)
   247  	case "M":
   248  		start = start.AddDate(0, incNum, 0)
   249  	case "D":
   250  		start = start.AddDate(0, 0, incNum)
   251  	case "w":
   252  		start = start.AddDate(0, 0, incNum*7)
   253  	case "h":
   254  		start = start.Add(time.Hour * time.Duration(incNum))
   255  	case "m":
   256  		start = start.Add(time.Minute * time.Duration(incNum))
   257  	case "s":
   258  		start = start.Add(time.Second * time.Duration(incNum))
   259  	default:
   260  	}
   261  	ret = start.Unix()
   262  	return
   263  }
   264  
   265  func increment(originalVal int64, incrementStr string) (ret int64) {
   266  	ret = originalVal
   267  
   268  	num, unit := parseTsExpr(incrementStr)
   269  	if num == 0 {
   270  		return
   271  	}
   272  
   273  	ret = incrementUnit(originalVal, num, unit)
   274  
   275  	return
   276  }
   277  
   278  func GenerateTimeItems(start int64, end int64, step int, unit string, repeat int, repeatTag string) []interface{} {
   279  	arr := make([]interface{}, 0)
   280  
   281  	total := 0
   282  	if repeatTag == "" {
   283  		for i := 0; true; {
   284  			val := incrementUnit(start, i*step, unit)
   285  			//val := start + int64(i*step)
   286  			if (val >= end && step > 0) || (val <= end && step < 0) {
   287  				break
   288  			}
   289  
   290  			for round := 0; round < repeat; round++ {
   291  				arr = append(arr, val)
   292  
   293  				total++
   294  				if total > consts.MaxNumb {
   295  					break
   296  				}
   297  			}
   298  
   299  			if total >= consts.MaxNumb {
   300  				break
   301  			}
   302  			i++
   303  		}
   304  	} else if repeatTag == "!" {
   305  		for round := 0; round < repeat; round++ {
   306  			for i := 0; true; {
   307  				val := start + incrementUnit(start, i*step, unit)
   308  				//val := start + int64(i*step)
   309  				if (val >= end && step > 0) || (val <= end && step < 0) {
   310  					break
   311  				}
   312  
   313  				arr = append(arr, val)
   314  
   315  				if total >= consts.MaxNumb {
   316  					break
   317  				}
   318  				i++
   319  			}
   320  
   321  			if total >= consts.MaxNumb {
   322  				break
   323  			}
   324  		}
   325  	}
   326  	return arr
   327  }