| 
									
										
										
										
											2015-07-18 23:39:12 +08:00
										 |  |  | package util | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2023-01-16 21:03:20 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2024-04-09 16:35:57 +08:00
										 |  |  | 	"regexp" | 
					
						
							| 
									
										
										
										
											2019-05-27 16:47:21 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-11-29 21:21:54 +08:00
										 |  |  | 	"unicode" | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-09 16:35:57 +08:00
										 |  |  | var stringListItemMatcher = regexp.MustCompile(`"[^"]+"|[^,\t\n\v\f\r ]+`) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 05:09:40 +08:00
										 |  |  | // StringsFallback2 returns the first of two not empty strings.
 | 
					
						
							| 
									
										
										
										
											2015-07-18 23:39:12 +08:00
										 |  |  | func StringsFallback2(val1 string, val2 string) string { | 
					
						
							| 
									
										
										
										
											2016-06-02 12:46:18 +08:00
										 |  |  | 	return stringsFallback(val1, val2) | 
					
						
							| 
									
										
										
										
											2015-07-18 23:39:12 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-08-10 19:46:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 05:09:40 +08:00
										 |  |  | // StringsFallback3 returns the first of three not empty strings.
 | 
					
						
							| 
									
										
										
										
											2015-08-10 19:46:59 +08:00
										 |  |  | func StringsFallback3(val1 string, val2 string, val3 string) string { | 
					
						
							| 
									
										
										
										
											2016-06-02 12:46:18 +08:00
										 |  |  | 	return stringsFallback(val1, val2, val3) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func stringsFallback(vals ...string) string { | 
					
						
							|  |  |  | 	for _, v := range vals { | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:54 +08:00
										 |  |  | 		if v != "" { | 
					
						
							|  |  |  | 			return v | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-08-10 19:46:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-02 12:46:18 +08:00
										 |  |  | 	return "" | 
					
						
							| 
									
										
										
										
											2015-08-10 19:46:59 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-09 16:35:57 +08:00
										 |  |  | // SplitString splits a string and returns a list of strings. It supports JSON list syntax and strings separated by commas or spaces.
 | 
					
						
							|  |  |  | // It supports quoted strings with spaces, e.g. "foo bar", "baz".
 | 
					
						
							| 
									
										
										
										
											2025-02-14 01:02:54 +08:00
										 |  |  | // It will return an empty list if it fails to parse the string.
 | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | func SplitString(str string) []string { | 
					
						
							| 
									
										
										
										
											2025-02-14 01:02:54 +08:00
										 |  |  | 	result, _ := SplitStringWithError(str) | 
					
						
							|  |  |  | 	return result | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SplitStringWithError splits a string and returns a list of strings. It supports JSON list syntax and strings separated by commas or spaces.
 | 
					
						
							|  |  |  | // It supports quoted strings with spaces, e.g. "foo bar", "baz".
 | 
					
						
							|  |  |  | // It returns an error if it cannot parse the string.
 | 
					
						
							|  |  |  | func SplitStringWithError(str string) ([]string, error) { | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | 	if len(str) == 0 { | 
					
						
							| 
									
										
										
										
											2025-02-14 01:02:54 +08:00
										 |  |  | 		return []string{}, nil | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-16 21:03:20 +08:00
										 |  |  | 	// JSON list syntax support
 | 
					
						
							|  |  |  | 	if strings.Index(strings.TrimSpace(str), "[") == 0 { | 
					
						
							|  |  |  | 		var res []string | 
					
						
							|  |  |  | 		err := json.Unmarshal([]byte(str), &res) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2025-02-14 01:02:54 +08:00
										 |  |  | 			return []string{}, fmt.Errorf("incorrect format: %s", str) | 
					
						
							| 
									
										
										
										
											2023-01-16 21:03:20 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-02-14 01:02:54 +08:00
										 |  |  | 		return res, nil | 
					
						
							| 
									
										
										
										
											2023-01-16 21:03:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-09 16:35:57 +08:00
										 |  |  | 	matches := stringListItemMatcher.FindAllString(str, -1) | 
					
						
							| 
									
										
										
										
											2024-06-15 02:16:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	result := make([]string, len(matches)) | 
					
						
							|  |  |  | 	for i, match := range matches { | 
					
						
							|  |  |  | 		result[i] = strings.Trim(match, "\"") | 
					
						
							| 
									
										
										
										
											2024-04-09 16:35:57 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-06-15 02:16:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-14 01:02:54 +08:00
										 |  |  | 	return result, nil | 
					
						
							| 
									
										
										
										
											2017-04-25 15:14:29 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 05:09:40 +08:00
										 |  |  | // GetAgeString returns a string representing certain time from years to minutes.
 | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | func GetAgeString(t time.Time) string { | 
					
						
							|  |  |  | 	if t.IsZero() { | 
					
						
							|  |  |  | 		return "?" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sinceNow := time.Since(t) | 
					
						
							|  |  |  | 	minutes := sinceNow.Minutes() | 
					
						
							|  |  |  | 	years := int(math.Floor(minutes / 525600)) | 
					
						
							|  |  |  | 	months := int(math.Floor(minutes / 43800)) | 
					
						
							|  |  |  | 	days := int(math.Floor(minutes / 1440)) | 
					
						
							|  |  |  | 	hours := int(math.Floor(minutes / 60)) | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 	var amount string | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	if years > 0 { | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 		if years == 1 { | 
					
						
							|  |  |  | 			amount = "year" | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			amount = "years" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return fmt.Sprintf("%d %s", years, amount) | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if months > 0 { | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 		if months == 1 { | 
					
						
							|  |  |  | 			amount = "month" | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			amount = "months" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return fmt.Sprintf("%d %s", months, amount) | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if days > 0 { | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 		if days == 1 { | 
					
						
							|  |  |  | 			amount = "day" | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			amount = "days" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return fmt.Sprintf("%d %s", days, amount) | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if hours > 0 { | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 		if hours == 1 { | 
					
						
							|  |  |  | 			amount = "hour" | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			amount = "hours" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return fmt.Sprintf("%d %s", hours, amount) | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if int(minutes) > 0 { | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 		if int(minutes) == 1 { | 
					
						
							|  |  |  | 			amount = "minute" | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			amount = "minutes" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return fmt.Sprintf("%d %s", int(minutes), amount) | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 21:53:58 +08:00
										 |  |  | 	return "< 1 minute" | 
					
						
							| 
									
										
										
										
											2017-08-09 16:36:41 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-27 16:47:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-17 01:36:26 +08:00
										 |  |  | func RemainingDaysUntil(expiration time.Time) string { | 
					
						
							|  |  |  | 	currentTime := time.Now() | 
					
						
							|  |  |  | 	durationUntil := expiration.Sub(currentTime) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	daysUntil := int(durationUntil.Hours() / 24) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-10 20:42:23 +08:00
										 |  |  | 	switch daysUntil { | 
					
						
							|  |  |  | 	case 0: | 
					
						
							| 
									
										
										
										
											2024-05-17 01:36:26 +08:00
										 |  |  | 		return "Today" | 
					
						
							| 
									
										
										
										
											2025-04-10 20:42:23 +08:00
										 |  |  | 	case 1: | 
					
						
							| 
									
										
										
										
											2024-05-17 01:36:26 +08:00
										 |  |  | 		return "Tomorrow" | 
					
						
							| 
									
										
										
										
											2025-04-10 20:42:23 +08:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2024-05-17 01:36:26 +08:00
										 |  |  | 		return fmt.Sprintf("%d days", daysUntil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 16:47:21 +08:00
										 |  |  | // ToCamelCase changes kebab case, snake case or mixed strings to camel case. See unit test for examples.
 | 
					
						
							|  |  |  | func ToCamelCase(str string) string { | 
					
						
							|  |  |  | 	var finalParts []string | 
					
						
							|  |  |  | 	parts := strings.Split(str, "_") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, part := range parts { | 
					
						
							|  |  |  | 		finalParts = append(finalParts, strings.Split(part, "-")...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for index, part := range finalParts[1:] { | 
					
						
							|  |  |  | 		finalParts[index+1] = strings.Title(part) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return strings.Join(finalParts, "") | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-29 21:21:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func Capitalize(s string) string { | 
					
						
							|  |  |  | 	if len(s) == 0 { | 
					
						
							|  |  |  | 		return s | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	r := []rune(s) | 
					
						
							|  |  |  | 	r[0] = unicode.ToUpper(r[0]) | 
					
						
							|  |  |  | 	return string(r) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-06 01:53:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func ByteCountSI(b int64) string { | 
					
						
							|  |  |  | 	const unit = 1000 | 
					
						
							|  |  |  | 	if b < unit { | 
					
						
							|  |  |  | 		return fmt.Sprintf("%d B", b) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	div, exp := int64(unit), 0 | 
					
						
							|  |  |  | 	for n := b / unit; n >= unit; n /= unit { | 
					
						
							|  |  |  | 		div *= unit | 
					
						
							|  |  |  | 		exp++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("%.1f %cB", | 
					
						
							|  |  |  | 		float64(b)/float64(div), "kMGTPE"[exp]) | 
					
						
							|  |  |  | } |