You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
7.9 KiB

2 years ago
  1. package util
  2. import (
  3. "fmt"
  4. "math"
  5. "strings"
  6. "time"
  7. gptypes "github.com/golang/protobuf/ptypes"
  8. gptime "github.com/golang/protobuf/ptypes/timestamp"
  9. "github.com/shopspring/decimal"
  10. "github.com/sirupsen/logrus"
  11. )
  12. const (
  13. DEFAULT_LAYOUT = "2006-01-02 15:04:05"
  14. DATE_LAYOUT = "2006-01-02"
  15. TIME_LAYOUT = "15:04:05"
  16. DEFAULT_TIME = "1900-01-01 00:00:00" //0000-00-00 00:00:00 0001-01-01 00:00:00
  17. STR_LAYOUT = "2006-01-02T15:04:05Z07:00"
  18. )
  19. func Now() time.Time {
  20. return time.Now().UTC()
  21. }
  22. func NowPtr() *time.Time {
  23. now := Now()
  24. return &now
  25. }
  26. func Format(layout string, t time.Time) string {
  27. return t.Format(layout)
  28. }
  29. func FormatByDefLay(t time.Time) string {
  30. return Format(DEFAULT_LAYOUT, t)
  31. }
  32. func Parse(layout string, s string) *time.Time {
  33. t, err := time.Parse(layout, s)
  34. if err != nil {
  35. panic(err)
  36. }
  37. return &t
  38. }
  39. func ParseByDefLay(s string) *time.Time {
  40. return Parse(DEFAULT_LAYOUT, s)
  41. }
  42. func IsDefaultTime(t time.Time) bool {
  43. defTime := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)
  44. return defTime.Equal(t.UTC())
  45. }
  46. //检查日期 t 是否为日期时间零值:0001-01-01 00:00:00 +0000 UTC
  47. func IsTimeZero(t time.Time) bool {
  48. timeZero := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
  49. return timeZero.Equal(t.UTC())
  50. }
  51. func Time2Ts(t time.Time) *gptime.Timestamp {
  52. if IsTimeZero(t) {
  53. return nil
  54. }
  55. ts, err := gptypes.TimestampProto(t)
  56. if err != nil {
  57. return nil
  58. }
  59. return ts
  60. }
  61. func Uint8ToTs(b *[]uint8) *gptime.Timestamp {
  62. if b == nil || len(*b) == 0 {
  63. return nil
  64. }
  65. s := string(*b)
  66. return Str2TsByDefLay(s)
  67. }
  68. func Ts2Time(ts *gptime.Timestamp) *time.Time {
  69. if ts == nil {
  70. return nil
  71. }
  72. t, err := gptypes.Timestamp(ts)
  73. if err != nil {
  74. logrus.Error(err)
  75. return nil
  76. }
  77. if IsTimeZero(t) {
  78. return nil
  79. }
  80. return &t
  81. }
  82. func Str2TsByDefLay(s string) *gptime.Timestamp {
  83. if s == "" {
  84. return nil
  85. }
  86. return Str2Ts("2006-01-02 15:04:05", s)
  87. }
  88. func Str2Ts(layout, s string) *gptime.Timestamp {
  89. if s == "" {
  90. return nil
  91. }
  92. if layout == "" {
  93. return Str2TsByDefLay(s)
  94. }
  95. t := Parse(layout, s)
  96. return Time2Ts(*t)
  97. }
  98. func Ts2StrByDefLay(ts *gptime.Timestamp) string {
  99. return Ts2Str("2006-01-02 15:04:05", ts)
  100. }
  101. func Ts2Str(layout string, ts *gptime.Timestamp) string {
  102. t := Ts2Time(ts)
  103. if t == nil {
  104. return ""
  105. }
  106. return Format(layout, *t)
  107. }
  108. //计算截止到当前时间,指定出生日期对应的年龄描述,如:不足1小时、1小时、1天、1个月、1 岁、1岁1个月、1岁1个月5天
  109. //
  110. func CovAgeCnAtNow(birth time.Time) (day int, ageCn string) {
  111. now := time.Now()
  112. if !Before(birth, now) {
  113. return 0, ""
  114. }
  115. since := now.Sub(birth)
  116. hoursSince := int(RoundDecimal(since.Hours(), 0))
  117. daySince := hoursSince / 24
  118. if hoursSince < 1.0 {
  119. return daySince, "不足一小时"
  120. }
  121. if hoursSince < 24 {
  122. return daySince, fmt.Sprintf("%d 小时", hoursSince)
  123. }
  124. yearSince := now.Year() - birth.Year()
  125. monthSince := now.Month() - birth.Month()
  126. //dayDiff := now.Day() - birth.Day()
  127. if yearSince == 0 { //同一年
  128. if monthSince == 0 { //同一月
  129. if daySince == 0 { //同一天
  130. return 0, "不足一天"
  131. } else if daySince > 0 {
  132. return daySince, fmt.Sprintf("%d 天", daySince)
  133. } else {
  134. return 0, ""
  135. }
  136. } else if monthSince > 0 {
  137. if daySince == 0 { //同一天
  138. return hoursSince / 24, fmt.Sprintf("%d 个月", monthSince)
  139. } else if daySince > 0 {
  140. return daySince, fmt.Sprintf("%d 天", daySince)
  141. } else {
  142. return 0, ""
  143. }
  144. } else {
  145. }
  146. } else if yearSince > 0 {
  147. } else {
  148. }
  149. return 0, ""
  150. }
  151. //根据结束日期和开始日期,计算年龄,返回包含年龄单位(岁、月、天)的字符串
  152. //开始日期一般为用户生日,结束日期一般为当前时间
  153. func CovAgeChinese(start time.Time, end time.Time) (float32, string) {
  154. if IsDefaultTime(start) {
  155. return 0, ""
  156. }
  157. //start = start.UTC()
  158. //end = end.UTC()
  159. diff := end.Unix() - start.Unix()
  160. if diff < 0 {
  161. return 0, ""
  162. }
  163. visitAge := decimal.NewFromFloat(float64(diff)).Div(decimal.NewFromFloat(float64(3600 * 365 * 24)))
  164. f64, _ := visitAge.Float64()
  165. y := decimal.NewFromFloat(float64(diff)).Div(decimal.NewFromFloat(float64(3600 * 365 * 24)))
  166. yf, _ := y.Float64()
  167. duration := end.Sub(start)
  168. //三个月以下
  169. if yf*12 < 3 {
  170. days := duration.Hours() / 24
  171. return float32(f64), fmt.Sprintf("%.0f天", math.Ceil(days))
  172. }
  173. //三个月以上三岁以下
  174. if yf*12 > 3 && yf < 3 {
  175. year := duration.Hours() / (24 * 365)
  176. years := int(year)
  177. months := (year - float64(years)) * 12
  178. months = math.Floor(months + 0.5)
  179. imonths := int(RoundDecimal(months, 0))
  180. sAge := fmt.Sprintf("%d岁", int(years))
  181. if imonths == 12 {
  182. sAge = fmt.Sprintf("%d岁", int(years+1))
  183. } else if imonths > 12 {
  184. sAge = fmt.Sprintf("%d岁%d个月", int(years+1), imonths-12)
  185. } else if imonths < 12 && imonths > 0 {
  186. if years == 0 {
  187. sAge = fmt.Sprintf("%d个月", imonths)
  188. } else {
  189. sAge = fmt.Sprintf("%d岁%d个月", int(years), imonths)
  190. }
  191. }
  192. return float32(f64), sAge
  193. }
  194. //三岁以上
  195. if yf > 3 {
  196. years := duration.Hours() / (24 * 365)
  197. years = RoundDecimal(years, 0)
  198. return float32(f64), fmt.Sprintf("%d岁", int(years))
  199. }
  200. return 0, ""
  201. /*age, ageUnit := CovAgeInt(start, end)
  202. if age <= 0 {
  203. return "未知"
  204. }
  205. return GetChineseAge(age, ageUnit)*/
  206. }
  207. func GetChineseAge(age int, ageUnit string) string {
  208. if age <= 0 {
  209. return ""
  210. }
  211. switch ageUnit {
  212. case "Y":
  213. return fmt.Sprintf("%d %s", age, "岁")
  214. case "M":
  215. return fmt.Sprintf("%d %s", age, "个月")
  216. case "D":
  217. return fmt.Sprintf("%d %s", age, "天")
  218. case "H":
  219. return "1 天" //fmt.Sprintf( "%d %s", num, "小时")
  220. case "m":
  221. return "1 天" //fmt.Sprintf( "%d %s", num, "分钟")
  222. case "S":
  223. return "1 天" //fmt.Sprintf( "%d %s", num, "秒")
  224. case "N":
  225. return "1 天" //fmt.Sprintf( "%d %s", num, "纳秒")
  226. default:
  227. return "1 天"
  228. }
  229. }
  230. func CovAgeInt(start time.Time, end time.Time) (int, string) {
  231. start = start.UTC()
  232. end = end.UTC()
  233. if !Before(start, end) {
  234. return 0, ""
  235. }
  236. if end.Year() > start.Year() { //不同年
  237. return end.Year() - start.Year(), "Y"
  238. } else { //同一年
  239. if end.Month() > start.Month() { //不同月
  240. return int(end.Month()) - int(start.Month()), "M"
  241. } else { //同一月
  242. if end.Day() > start.Day() { //不同天
  243. return end.Day() - start.Day(), "D"
  244. } else { //同一天
  245. if end.Hour() > start.Hour() { //不同小时
  246. return end.Hour() - start.Hour(), "H"
  247. } else { //同一小时
  248. if end.Minute() > start.Minute() { //不同分钟
  249. return end.Minute() - start.Minute(), "m"
  250. } else { //同一分钟
  251. if end.Second() > start.Second() { //不同秒
  252. return end.Second() - start.Second(), "S"
  253. }
  254. }
  255. }
  256. }
  257. }
  258. }
  259. return end.Nanosecond() - start.Nanosecond(), "N"
  260. }
  261. //判断是否start为早于end的时间,只判断年月日
  262. func Before(start time.Time, end time.Time) bool {
  263. if start.Year() < end.Year() {
  264. return true
  265. }
  266. if start.Year() > end.Year() {
  267. return false
  268. }
  269. if start.Year() == end.Year() { //同一年
  270. if start.Month() < end.Month() {
  271. return true
  272. }
  273. if start.Month() > end.Month() {
  274. return false
  275. }
  276. if start.Month() == end.Month() { //同一月
  277. if start.Day() < end.Day() {
  278. return true
  279. }
  280. if start.Day() > end.Day() {
  281. return false
  282. }
  283. if start.Day() == end.Day() {
  284. return true //同一天,暂时返回true
  285. }
  286. }
  287. }
  288. return end.Nanosecond() >= start.Nanosecond()
  289. }
  290. func StartTime(t time.Time) time.Time {
  291. return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
  292. }
  293. func EndTime(t time.Time) time.Time {
  294. return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, t.Location())
  295. }
  296. func Strisemptyorzerotime(str string) (res *time.Time) {
  297. if strings.TrimSpace(str) == "" {
  298. return nil
  299. }
  300. t1, e1 := time.Parse(DEFAULT_LAYOUT, str)
  301. if e1 != nil {
  302. t2, e2 := time.Parse(STR_LAYOUT, str)
  303. if e2 != nil {
  304. //
  305. t3, e3 := time.Parse(DATE_LAYOUT, str)
  306. if e3 != nil {
  307. //
  308. return nil
  309. }
  310. return &t3
  311. }
  312. return &t2
  313. }
  314. return &t1
  315. }