github.com/webx-top/com@v1.2.12/time.go (about)

     1  // Copyright 2013 com authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package com
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"regexp"
    21  	"strconv"
    22  	"strings"
    23  	"time"
    24  )
    25  
    26  // Date Format unix time int64 to string
    27  func Date(ti int64, format string) string {
    28  	t := time.Unix(int64(ti), 0)
    29  	return DateT(t, format)
    30  }
    31  
    32  // DateS Format unix time string to string
    33  func DateS(ts string, format string) string {
    34  	i, _ := strconv.ParseInt(ts, 10, 64)
    35  	return Date(i, format)
    36  }
    37  
    38  // DateT Format time.Time struct to string
    39  // MM - month - 01
    40  // M - month - 1, single bit
    41  // DD - day - 02
    42  // D - day 2
    43  // YYYY - year - 2006
    44  // YY - year - 06
    45  // HH - 24 hours - 03
    46  // H - 24 hours - 3
    47  // hh - 12 hours - 03
    48  // h - 12 hours - 3
    49  // mm - minute - 04
    50  // m - minute - 4
    51  // ss - second - 05
    52  // s - second = 5
    53  func DateT(t time.Time, format string) string {
    54  	res := strings.Replace(format, "MM", t.Format("01"), -1)
    55  	res = strings.Replace(res, "M", t.Format("1"), -1)
    56  	res = strings.Replace(res, "DD", t.Format("02"), -1)
    57  	res = strings.Replace(res, "D", t.Format("2"), -1)
    58  	res = strings.Replace(res, "YYYY", t.Format("2006"), -1)
    59  	res = strings.Replace(res, "YY", t.Format("06"), -1)
    60  	res = strings.Replace(res, "HH", fmt.Sprintf("%02d", t.Hour()), -1)
    61  	res = strings.Replace(res, "H", fmt.Sprintf("%d", t.Hour()), -1)
    62  	res = strings.Replace(res, "hh", t.Format("03"), -1)
    63  	res = strings.Replace(res, "h", t.Format("3"), -1)
    64  	res = strings.Replace(res, "mm", t.Format("04"), -1)
    65  	res = strings.Replace(res, "m", t.Format("4"), -1)
    66  	res = strings.Replace(res, "ss", t.Format("05"), -1)
    67  	res = strings.Replace(res, "s", t.Format("5"), -1)
    68  	return res
    69  }
    70  
    71  // DateFormat pattern rules.
    72  var datePatterns = []string{
    73  	// year
    74  	"Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
    75  	"y", "06", //A two digit representation of a year Examples: 99 or 03
    76  	// month
    77  	"m", "01", // Numeric representation of a month, with leading zeros 01 through 12
    78  	"n", "1", // Numeric representation of a month, without leading zeros 1 through 12
    79  	"M", "Jan", // A short textual representation of a month, three letters Jan through Dec
    80  	"F", "January", // A full textual representation of a month, such as January or March January through December
    81  	// day
    82  	"d", "02", // Day of the month, 2 digits with leading zeros 01 to 31
    83  	"j", "2", // Day of the month without leading zeros 1 to 31
    84  	// week
    85  	"D", "Mon", // A textual representation of a day, three letters Mon through Sun
    86  	"l", "Monday", // A full textual representation of the day of the week Sunday through Saturday
    87  	// time
    88  	"g", "3", // 12-hour format of an hour without leading zeros 1 through 12
    89  	"G", "15", // 24-hour format of an hour without leading zeros 0 through 23
    90  	"h", "03", // 12-hour format of an hour with leading zeros 01 through 12
    91  	"H", "15", // 24-hour format of an hour with leading zeros 00 through 23
    92  	"a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm
    93  	"A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM
    94  	"i", "04", // Minutes with leading zeros 00 to 59
    95  	"s", "05", // Seconds, with leading zeros 00 through 59
    96  	// time zone
    97  	"T", "MST",
    98  	"P", "-07:00",
    99  	"O", "-0700",
   100  	// RFC 2822
   101  	"r", time.RFC1123Z,
   102  }
   103  
   104  // DateFormatReplacer .
   105  var DateFormatReplacer = strings.NewReplacer(datePatterns...)
   106  
   107  // DateParse Parse Date use PHP time format.
   108  func DateParse(dateString, format string) (time.Time, error) {
   109  	return time.ParseInLocation(ConvDateFormat(format), dateString, time.Local)
   110  }
   111  
   112  // ConvDateFormat Convert PHP time format.
   113  func ConvDateFormat(format string) string {
   114  	format = DateFormatReplacer.Replace(format)
   115  	return format
   116  }
   117  
   118  // DateFormat 将时间戳格式化为日期字符窜
   119  func DateFormat(format string, timestamp interface{}) (t string) { // timestamp
   120  	switch format {
   121  	case "Y-m-d H:i:s", "":
   122  		format = "2006-01-02 15:04:05"
   123  	case "Y-m-d H:i":
   124  		format = "2006-01-02 15:04"
   125  	case "y-m-d H:i":
   126  		format = "06-01-02 15:04"
   127  	case "m-d H:i":
   128  		format = "01-02 15:04"
   129  	case "Y-m-d":
   130  		format = "2006-01-02"
   131  	case "y-m-d":
   132  		format = "06-01-02"
   133  	case "m-d":
   134  		format = "01-02"
   135  	default:
   136  		format = ConvDateFormat(format)
   137  	}
   138  	sd := Int64(timestamp)
   139  	t = time.Unix(sd, 0).Format(format)
   140  	return
   141  }
   142  
   143  // StrToTime 日期字符窜转为时间戳数字
   144  func StrToTime(str string, args ...string) (unixtime int) {
   145  	layout := "2006-01-02 15:04:05"
   146  	if len(args) > 0 {
   147  		layout = args[0]
   148  	}
   149  	t, err := time.ParseInLocation(layout, str, time.Local)
   150  	if err == nil {
   151  		unixtime = int(t.Unix())
   152  	} else {
   153  		fmt.Println(err, str)
   154  	}
   155  	return
   156  }
   157  
   158  // RestoreTime 从字符串还原时间
   159  // RestoreTime(`2001-01-01T00:00:03Z`).Format(`2006-01-02 15:04:05`) => 2001-01-01 00:00:03
   160  func RestoreTime(str string, args ...string) time.Time {
   161  	layout := time.RFC3339
   162  	if len(args) > 0 {
   163  		layout = args[0]
   164  	}
   165  	t, _ := time.ParseInLocation(layout, str, time.Local)
   166  	return t
   167  }
   168  
   169  // FormatByte 兼容以前的版本,FormatBytes别名
   170  // @param float64 size
   171  // @param int precision
   172  // @param bool trimRightZero
   173  func FormatByte(args ...interface{}) string {
   174  	return FormatBytes(args...)
   175  }
   176  
   177  var sizeUnits = [...]string{"YB", "ZB", "EB", "PB", "TB", "GB", "MB", "KB", "B"}
   178  
   179  // FormatBytes 格式化字节。 FormatBytes(字节整数,保留小数位数, 是否裁剪掉小数中的后缀0)
   180  // 不设置 参数 2 和 参数 3 时,默认保留2为小数并裁剪小数中的后缀0
   181  // @param float64 size
   182  // @param int precision
   183  // @param bool trimRightZero
   184  func FormatBytes(args ...interface{}) string {
   185  	var (
   186  		total         = len(sizeUnits)
   187  		size          float64
   188  		precision     int
   189  		trimRightZero bool
   190  	)
   191  	switch len(args) {
   192  	case 3:
   193  		trimRightZero = Bool(args[2])
   194  		fallthrough
   195  	case 2:
   196  		precision = Int(args[1])
   197  		size = Float64(args[0])
   198  	case 1:
   199  		trimRightZero = true
   200  		precision = 2
   201  		size = Float64(args[0])
   202  	}
   203  	for total--; total > 0 && size > 1024.0; total-- {
   204  		size /= 1024.0
   205  	}
   206  	r := fmt.Sprintf("%.*f", precision, size)
   207  	if trimRightZero {
   208  		r = NumberTrimZero(r)
   209  	}
   210  	return r + sizeUnits[total]
   211  }
   212  
   213  // DateFormatShort 格式化耗时
   214  func DateFormatShort(timestamp interface{}) string {
   215  	now := time.Now()
   216  	year := now.Year()
   217  	month := now.Month()
   218  	day := now.Day()
   219  	cTime := StrToTime(fmt.Sprintf(`%d-%.2d-%.2d 00:00:00`, year, month, day)) //月、日始终保持两位
   220  	timestamp2 := Int(timestamp)
   221  	if cTime < timestamp2 {
   222  		return DateFormat("15:04", timestamp)
   223  	}
   224  	cTime = StrToTime(fmt.Sprintf(`%d-01-01 00:00:00`, year))
   225  	if cTime < timestamp2 {
   226  		return DateFormat("01-02", timestamp)
   227  	}
   228  	return DateFormat("06-01-02", timestamp)
   229  }
   230  
   231  // FormatPastTime 格式化耗时
   232  // @param number timestamp
   233  // @param string args[0] 时间格式
   234  // @param string args[1] 已过去时间后缀
   235  // @param string args[2] 语种
   236  func FormatPastTime(timestamp interface{}, args ...string) string {
   237  	argSize := len(args)
   238  	duration := time.Since(time.Unix(Int64(timestamp), 0))
   239  	if duration >= time.Hour*24 {
   240  		format := "Y-m-d H:i:s"
   241  		if argSize > 0 && len(args[0]) > 0 {
   242  			format = args[0]
   243  		}
   244  		return DateFormat(format, timestamp)
   245  	}
   246  	var suffix string
   247  	var language string
   248  	if argSize > 1 {
   249  		suffix = args[1]
   250  		if len(suffix) > 0 && !HasChineseFirst(suffix) {
   251  			suffix = ` ` + suffix
   252  		}
   253  		if argSize > 2 {
   254  			language = args[2]
   255  		}
   256  	}
   257  	return FriendlyTime(duration, suffix, 0, true, language)
   258  }
   259  
   260  // FriendlyTime 对人类友好的经历时间格式
   261  // @param time.Duration d
   262  // @param string suffix
   263  // @param int precision
   264  // @param bool trimRightZero
   265  // @param string language
   266  func FriendlyTime(d time.Duration, args ...interface{}) (r string) {
   267  	var suffix string
   268  	var trimRightZero bool
   269  	var language string
   270  	precision := 2
   271  	switch len(args) {
   272  	case 4:
   273  		language = String(args[3])
   274  		fallthrough
   275  	case 3:
   276  		trimRightZero = Bool(args[2])
   277  		fallthrough
   278  	case 2:
   279  		precision = Int(args[1])
   280  		fallthrough
   281  	case 1:
   282  		suffix = String(args[0])
   283  	}
   284  	var unit string
   285  	var divisor float64
   286  	u := uint64(d)
   287  	if u < uint64(time.Second) {
   288  		switch {
   289  		case u == 0:
   290  			unit = `s`
   291  		case u < uint64(time.Microsecond):
   292  			unit = `ns` //纳秒
   293  			divisor = 1
   294  		case u < uint64(time.Millisecond):
   295  			unit = `us` //微秒
   296  			divisor = 1000
   297  		default:
   298  			unit = `ms` //毫秒
   299  			divisor = 1000 * 1000
   300  		}
   301  	} else {
   302  		divisor = 1000 * 1000 * 1000
   303  		switch {
   304  		case u < uint64(time.Minute):
   305  			unit = `s` //秒
   306  		case u < uint64(time.Hour):
   307  			unit = `m` //分钟
   308  			divisor *= 60
   309  		case u < uint64(time.Hour)*24:
   310  			unit = `h` //小时
   311  			divisor *= 60 * 60
   312  		case u < uint64(time.Hour)*24*7:
   313  			unit = `d` //天
   314  			divisor *= 60 * 60 * 24
   315  		default:
   316  			unit = `w` //周
   317  			divisor *= 60 * 60 * 24 * 7
   318  		}
   319  	}
   320  	if divisor > 0 {
   321  		r = fmt.Sprintf("%.*f", precision, float64(u)/divisor)
   322  		if trimRightZero {
   323  			r = NumberTrimZero(r)
   324  		}
   325  	} else {
   326  		r = `0`
   327  	}
   328  	if len(language) > 0 {
   329  		units, ok := TimeShortUnits[language]
   330  		if ok {
   331  			if ut, ok := units[unit]; ok {
   332  				unit = ut
   333  			}
   334  		}
   335  	}
   336  	r += unit + suffix
   337  	return
   338  }
   339  
   340  // StartTime 开始时间
   341  var StartTime = time.Now()
   342  
   343  // TotalRunTime 总运行时长
   344  func TotalRunTime() string {
   345  	return FriendlyTime(time.Since(StartTime))
   346  }
   347  
   348  var (
   349  	timeUnits     = []string{"years", "weeks", "days", "hours", "minutes", "seconds", "milliseconds"}
   350  	timeUnitsZhCN = map[string]string{"years": "年", "weeks": "周", "days": "天", "hours": "小时", "minutes": "分", "seconds": "秒", "milliseconds": "毫秒"}
   351  	// TimeUnits 多语言时间单位
   352  	TimeUnits = map[string]map[string]string{`zh-cn`: timeUnitsZhCN}
   353  
   354  	// TimeShortUnits 时间单位(简写)
   355  	TimeShortUnits = map[string]map[string]string{
   356  		`zh-cn`: {`s`: `秒`, `ns`: `纳秒`, `us`: `微秒`, `ms`: `毫秒`, `m`: `分钟`, `h`: `小时`, `d`: `天`, `w`: `周`},
   357  	}
   358  )
   359  
   360  // Durafmt holds the parsed duration and the original input duration.
   361  type Durafmt struct {
   362  	duration time.Duration
   363  	input    string // Used as reference.
   364  	units    map[string]string
   365  }
   366  
   367  func getDurationUnits(args []interface{}) map[string]string {
   368  	var units map[string]string
   369  	if len(args) > 0 {
   370  		switch v := args[0].(type) {
   371  		case map[string]string:
   372  			units = v
   373  		case string:
   374  			var ok bool
   375  			units, ok = TimeUnits[v]
   376  			if ok {
   377  				return units
   378  			}
   379  			switch strings.ToLower(v) {
   380  			case `zh_cn`, `zh-cn`:
   381  				units = timeUnitsZhCN
   382  			}
   383  		}
   384  	}
   385  	return units
   386  }
   387  
   388  // ParseDuration creates a new *Durafmt struct, returns error if input is invalid.
   389  func ParseDuration(dinput time.Duration, args ...interface{}) *Durafmt {
   390  	input := dinput.String()
   391  	return &Durafmt{dinput, input, getDurationUnits(args)}
   392  }
   393  
   394  // ParseDurationString creates a new *Durafmt struct from a string.
   395  // returns an error if input is invalid.
   396  func ParseDurationString(input string, args ...interface{}) (*Durafmt, error) {
   397  	if input == "0" || input == "-0" {
   398  		return nil, errors.New("durafmt: missing unit in duration " + input)
   399  	}
   400  	duration, err := time.ParseDuration(input)
   401  	if err != nil {
   402  		return nil, err
   403  	}
   404  	return &Durafmt{duration, input, getDurationUnits(args)}, nil
   405  }
   406  
   407  func (d *Durafmt) Duration() time.Duration {
   408  	return d.duration
   409  }
   410  
   411  // String parses d *Durafmt into a human readable duration.
   412  func (d *Durafmt) String() string {
   413  	var duration string
   414  
   415  	// Check for minus durations.
   416  	if string(d.input[0]) == "-" {
   417  		duration += "-"
   418  		d.duration = -d.duration
   419  	}
   420  
   421  	// Convert duration.
   422  	seconds := int64(d.duration.Seconds()) % 60
   423  	minutes := int64(d.duration.Minutes()) % 60
   424  	hours := int64(d.duration.Hours()) % 24
   425  	days := int64(d.duration/(24*time.Hour)) % 365 % 7
   426  	weeks := int64(d.duration/(24*time.Hour)) / 7 % 52
   427  	years := int64(d.duration/(24*time.Hour)) / 365
   428  	milliseconds := int64(d.duration/time.Millisecond) -
   429  		(seconds * 1000) - (minutes * 60000) - (hours * 3600000) -
   430  		(days * 86400000) - (weeks * 604800000) - (years * 31536000000)
   431  
   432  	// Create a map of the converted duration time.
   433  	durationMap := map[string]int64{
   434  		"milliseconds": milliseconds,
   435  		"seconds":      seconds,
   436  		"minutes":      minutes,
   437  		"hours":        hours,
   438  		"days":         days,
   439  		"weeks":        weeks,
   440  		"years":        years,
   441  	}
   442  
   443  	// Construct duration string.
   444  	for _, u := range timeUnits {
   445  		v := durationMap[u]
   446  		if customLable, ok := d.units[u]; ok {
   447  			u = customLable
   448  		}
   449  		strval := strconv.FormatInt(v, 10)
   450  		switch {
   451  		// add to the duration string if v > 1.
   452  		case v > 1:
   453  			duration += strval + " " + u + " "
   454  		// remove the plural 's', if v is 1.
   455  		case v == 1:
   456  			duration += strval + " " + strings.TrimRight(u, "s") + " "
   457  		// omit any value with 0s or 0.
   458  		case d.duration.String() == "0" || d.duration.String() == "0s":
   459  			// note: milliseconds and minutes have the same suffix (m)
   460  			// so we have to check if the units match with the suffix.
   461  
   462  			// check for a suffix that is NOT the milliseconds suffix.
   463  			if strings.HasSuffix(d.input, string(u[0])) && !strings.Contains(d.input, "ms") {
   464  				// if it happens that the units are milliseconds, skip.
   465  				if u == "milliseconds" {
   466  					continue
   467  				}
   468  				duration += strval + " " + u
   469  			}
   470  			// process milliseconds here.
   471  			if u == "milliseconds" {
   472  				if strings.Contains(d.input, "ms") {
   473  					duration += strval + " " + u
   474  					break
   475  				}
   476  			}
   477  			break
   478  		// omit any value with 0.
   479  		case v == 0:
   480  			continue
   481  		}
   482  	}
   483  	// trim any remaining spaces.
   484  	duration = strings.TrimSpace(duration)
   485  	return duration
   486  }
   487  
   488  // NowStr 当前时间字符串
   489  func NowStr() string {
   490  	return time.Now().Format(`2006-01-02 15:04:05`)
   491  }
   492  
   493  func NewTime(t time.Time) *Time {
   494  	return &Time{Time: t}
   495  }
   496  
   497  type Time struct {
   498  	time.Time
   499  }
   500  
   501  func (t Time) ParseTimestamp(timestamp interface{}) time.Time {
   502  	return time.Unix(Int64(timestamp), 0)
   503  }
   504  
   505  func (t Time) SubTimestamp(timestamp interface{}) time.Duration {
   506  	return t.Sub(t.ParseTimestamp(timestamp))
   507  }
   508  
   509  func (t Time) IsToday(timestamp interface{}) bool {
   510  	st := t.ParseTimestamp(timestamp)
   511  	return st.Day() == t.Day() && st.Month() == t.Month() && st.Year() == t.Year()
   512  }
   513  
   514  func (t Time) IsThisMonth(timestamp interface{}) bool {
   515  	st := t.ParseTimestamp(timestamp)
   516  	return st.Month() == t.Month() && st.Year() == t.Year()
   517  }
   518  
   519  func (t Time) IsThisYear(timestamp interface{}) bool {
   520  	st := t.ParseTimestamp(timestamp)
   521  	return st.Year() == t.Year()
   522  }
   523  
   524  func (t Time) IsAgo(timestamp interface{}, days int, units ...int) bool {
   525  	unit := 86400
   526  	if len(units) > 0 {
   527  		unit = units[0]
   528  	}
   529  	return t.SubTimestamp(timestamp) > time.Second*time.Duration(days*unit)
   530  }
   531  
   532  func (t Time) IsFuture(timestamp interface{}, days int, units ...int) bool {
   533  	unit := 86400
   534  	if len(units) > 0 {
   535  		unit = units[0]
   536  	}
   537  	st := t.ParseTimestamp(timestamp)
   538  	return t.Unix()+int64(days*unit) <= st.Unix()
   539  }
   540  
   541  func (t Time) IsAfter(timestamp interface{}, agoDays int, units ...int) bool {
   542  	unit := 86400
   543  	if len(units) > 0 {
   544  		unit = units[0]
   545  	}
   546  	st := t.ParseTimestamp(timestamp)
   547  	return t.Unix()-int64(agoDays*unit) <= st.Unix()
   548  }
   549  
   550  var numberSpitRule = regexp.MustCompile(`[^\d]+`)
   551  var MinYear = 1000
   552  var MaxYear = 9999
   553  
   554  func FixDateString(dateStr string) string {
   555  	parts := numberSpitRule.Split(dateStr, 3)
   556  	dateArr := make([]string, 3)
   557  	switch len(parts) {
   558  	case 3:
   559  		// day
   560  		if len(parts[2]) < 2 {
   561  			parts[2] = `0` + parts[2]
   562  		} else {
   563  			day, _ := strconv.Atoi(strings.TrimPrefix(parts[2], `0`))
   564  			if day < 0 || day > 31 {
   565  				return ``
   566  			}
   567  		}
   568  		dateArr[2] = parts[2]
   569  		fallthrough
   570  	case 2:
   571  		// month
   572  		if len(parts[1]) < 2 {
   573  			parts[1] = `0` + parts[1]
   574  		} else {
   575  			month, _ := strconv.Atoi(strings.TrimPrefix(parts[1], `0`))
   576  			if month <= 0 || month > 12 {
   577  				return ``
   578  			}
   579  		}
   580  		dateArr[1] = parts[1]
   581  		fallthrough
   582  	case 1:
   583  		// year
   584  		year, _ := strconv.Atoi(parts[0])
   585  		if year <= MinYear || year > MaxYear {
   586  			return ``
   587  		}
   588  		dateArr[0] = parts[0]
   589  	}
   590  	if len(dateArr[1]) == 0 {
   591  		dateArr[1] = `01`
   592  	}
   593  	if len(dateArr[2]) == 0 {
   594  		dateArr[2] = `01`
   595  	}
   596  	return strings.Join(dateArr, `-`)
   597  }
   598  
   599  func FixTimeString(timeStr string) string {
   600  	parts := numberSpitRule.Split(timeStr, 3)
   601  	timeArr := make([]string, 3)
   602  	switch len(parts) {
   603  	case 3:
   604  		// second
   605  		if len(parts[2]) < 2 {
   606  			parts[2] = `0` + parts[2]
   607  		} else {
   608  			seconds, _ := strconv.Atoi(strings.TrimPrefix(parts[2], `0`))
   609  			if seconds < 0 || seconds > 59 {
   610  				return ``
   611  			}
   612  		}
   613  		timeArr[2] = parts[2]
   614  		fallthrough
   615  	case 2:
   616  		// minute
   617  		if len(parts[1]) < 2 {
   618  			parts[1] = `0` + parts[1]
   619  		} else {
   620  			minutes, _ := strconv.Atoi(strings.TrimPrefix(parts[1], `0`))
   621  			if minutes < 0 || minutes > 59 {
   622  				return ``
   623  			}
   624  		}
   625  		timeArr[1] = parts[1]
   626  		fallthrough
   627  	case 1:
   628  		// hour
   629  		if len(parts[0]) < 2 {
   630  			parts[0] = `0` + parts[0]
   631  		} else {
   632  			hour, _ := strconv.Atoi(strings.TrimPrefix(parts[0], `0`))
   633  			if hour < 0 || hour > 23 {
   634  				return ``
   635  			}
   636  		}
   637  		timeArr[0] = parts[0]
   638  	}
   639  	if len(timeArr[1]) == 0 {
   640  		timeArr[1] = `00`
   641  	}
   642  	if len(timeArr[2]) == 0 {
   643  		timeArr[2] = `00`
   644  	}
   645  	return strings.Join(timeArr, `:`)
   646  }
   647  
   648  func FixDateTimeString(dateTimeStr string) []string {
   649  	parts := strings.SplitN(dateTimeStr, ` `, 2)
   650  	var dateStr string
   651  	if len(parts) == 2 {
   652  		dateStr = FixDateString(parts[0])
   653  		if len(dateStr) == 0 {
   654  			return nil
   655  		}
   656  		timeStr := FixTimeString(parts[1])
   657  		if len(timeStr) == 0 {
   658  			return []string{dateStr}
   659  		}
   660  		return []string{dateStr, timeStr}
   661  	}
   662  	dateStr = FixDateString(parts[0])
   663  	if len(dateStr) == 0 {
   664  		return nil
   665  	}
   666  	return []string{dateStr}
   667  }