github.com/whatap/golib@v0.0.22/util/dateutil/DateTimeHelper.go (about)

     1  package dateutil
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strconv"
     7  	"sync"
     8  	"time"
     9  )
    10  
    11  const (
    12  	MILLIS_PER_SECOND      = 1000
    13  	MILLIS_PER_MINUTE      = 60 * MILLIS_PER_SECOND
    14  	MILLIS_PER_FIVE_MINUTE = 5 * 60 * MILLIS_PER_SECOND
    15  	MILLIS_PER_TEN_MINUTE  = 10 * MILLIS_PER_MINUTE
    16  	MILLIS_PER_HOUR        = 60 * MILLIS_PER_MINUTE
    17  	MILLIS_PER_DAY         = 24 * MILLIS_PER_HOUR
    18  )
    19  
    20  type Day struct {
    21  	yyyy int
    22  	mm   int
    23  	dd   int
    24  	date string
    25  	wday string
    26  	time int64
    27  }
    28  type DateTimeHelper struct {
    29  	BASE_TIME int64
    30  	table     [][][]*Day
    31  	dateTable []*Day
    32  	LAST_DATE int
    33  }
    34  
    35  var wday = []string{"Mon", "Tue", "Wed", "Thr", "Fri", "Sat", "Sun"}
    36  var mdayLen = []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    37  
    38  func newDateTimeHelper(location string) *DateTimeHelper {
    39  	d := new(DateTimeHelper)
    40  	d.BASE_TIME = 0
    41  	d.table = make([][][]*Day, 100)
    42  	d.dateTable = make([]*Day, 40000)
    43  	d.LAST_DATE = 0
    44  
    45  	// BASE_TIME 생성 location 이 없을 경우 time.UTC 로 설정.
    46  	if location != "" {
    47  		loc, _ := time.LoadLocation(location)
    48  		//t, _ := time.ParseInLocation(time.RFC3339, "2001-01-01T00:00:00Z", loc)
    49  		t := time.Date(2000, time.January, 1, 0, 0, 0, 0, loc)
    50  		d.BASE_TIME = t.Unix() * 1000
    51  	} else {
    52  		//t, _ := time.Parse(time.RFC3339, "2001-01-01T00:00:00Z")
    53  		t := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
    54  		d.BASE_TIME = t.Unix() * 1000
    55  	}
    56  	d.open()
    57  
    58  	return d
    59  }
    60  
    61  var lock sync.Mutex
    62  var _table = make(map[string]*DateTimeHelper)
    63  
    64  func getDateTimeHelper(timezone string) *DateTimeHelper {
    65  	lock.Lock()
    66  	defer lock.Unlock()
    67  
    68  	helper := _table[timezone]
    69  	if helper == nil {
    70  		helper = newDateTimeHelper(timezone)
    71  		_table[timezone] = helper
    72  	}
    73  	return helper
    74  }
    75  
    76  func (this *DateTimeHelper) open() {
    77  	mtime := this.BASE_TIME
    78  	seq := 0
    79  	wdayIdx := 5 // 20000101:Saturday
    80  	for year := 0; year < 100; year += 1 {
    81  		this.table[year] = make([][]*Day, 12)
    82  		for mm := 0; mm < 12; mm++ {
    83  			monLen := mdayLen[mm]
    84  			if mm == 1 && isYun(year) {
    85  				monLen++
    86  			}
    87  			this.table[year][mm] = make([]*Day, monLen)
    88  			for dd := 0; dd < monLen; dd++ {
    89  				yyyyMMdd := fmt.Sprintf("%d%02d%02d", (year + 2000), mm+1, dd+1)
    90  				this.dateTable[seq] = new(Day)
    91  				this.dateTable[seq].date = yyyyMMdd
    92  				this.dateTable[seq].yyyy = year + 2000
    93  				this.dateTable[seq].mm = mm + 1
    94  				this.dateTable[seq].dd = dd + 1
    95  				this.dateTable[seq].wday = wday[wdayIdx]
    96  				this.dateTable[seq].time = mtime
    97  				this.table[year][mm][dd] = this.dateTable[seq]
    98  
    99  				if wdayIdx == 6 {
   100  					wdayIdx = 0
   101  				} else {
   102  					wdayIdx += 1
   103  				}
   104  				seq += 1
   105  				mtime += MILLIS_PER_DAY
   106  			}
   107  		}
   108  	}
   109  }
   110  func isYun(year int) bool {
   111  	if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
   112  		return true
   113  	} else {
   114  		return false
   115  	}
   116  }
   117  func (this *DateTimeHelper) getYmdTime(yyyyMMdd string) int64 {
   118  	if yyyyMMdd == "" {
   119  		return 0
   120  	}
   121  	year, _ := strconv.Atoi(yyyyMMdd[0:4])
   122  	mm, _ := strconv.Atoi(yyyyMMdd[4:6])
   123  	dd, _ := strconv.Atoi(yyyyMMdd[6:8])
   124  	if year >= 2100 {
   125  		return this.table[99][11][30].time + MILLIS_PER_DAY
   126  	}
   127  	if year < 2000 {
   128  		return this.BASE_TIME
   129  	}
   130  	return this.table[year-2000][mm-1][dd-1].time
   131  }
   132  func (this *DateTimeHelper) getWeekDay(yyyyMMdd string) string {
   133  	if yyyyMMdd == "" {
   134  		return ""
   135  	}
   136  	year, _ := strconv.Atoi(yyyyMMdd[0:4])
   137  	mm, _ := strconv.Atoi(yyyyMMdd[4:6])
   138  	dd, _ := strconv.Atoi(yyyyMMdd[6:8])
   139  	if year >= 2100 {
   140  		return this.table[99][11][30].wday
   141  	}
   142  	if year < 2000 {
   143  		return this.table[0][0][0].wday
   144  	}
   145  	return this.table[year-2000][mm-1][dd-1].wday
   146  }
   147  func (this *DateTimeHelper) hhmmTo(date string) int64 {
   148  	if date == "" {
   149  		return 0
   150  	}
   151  	h, _ := strconv.Atoi(date[0:2])
   152  	m, _ := strconv.Atoi(date[2:4])
   153  	return int64(h*MILLIS_PER_HOUR + m*MILLIS_PER_MINUTE)
   154  }
   155  func (this *DateTimeHelper) yyyymmdd(time int64) string {
   156  	idx := int((time - this.BASE_TIME) / MILLIS_PER_DAY)
   157  	if idx < 0 {
   158  		idx = 0
   159  	}
   160  	return this.dateTable[idx].date
   161  }
   162  func (this *DateTimeHelper) weekday(time int64) string {
   163  	idx := int((time - this.BASE_TIME) / MILLIS_PER_DAY)
   164  	if idx < 0 {
   165  		idx = 0
   166  	}
   167  	return this.dateTable[idx].wday
   168  }
   169  func (this *DateTimeHelper) datetime(time int64) string {
   170  	if time < this.BASE_TIME {
   171  		return "20000101 00:00:00"
   172  	}
   173  	idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   174  	dtime := (int)((time - this.BASE_TIME) % MILLIS_PER_DAY)
   175  	hh := (int)(dtime / MILLIS_PER_HOUR)
   176  	dtime = (int)(dtime % MILLIS_PER_HOUR)
   177  	mm := (int)(dtime / MILLIS_PER_MINUTE)
   178  	dtime = (int)(dtime % MILLIS_PER_MINUTE)
   179  	ss := (int)(dtime / MILLIS_PER_SECOND)
   180  
   181  	var buffer bytes.Buffer
   182  	buffer.WriteString(this.dateTable[idx].date)
   183  	buffer.WriteString(" ")
   184  	buffer.WriteString(mk2(hh))
   185  	buffer.WriteString(":")
   186  	buffer.WriteString(mk2(mm))
   187  	buffer.WriteString(":")
   188  	buffer.WriteString(mk2(ss))
   189  	return buffer.String()
   190  }
   191  func (this *DateTimeHelper) timestamp(time int64) string {
   192  	if time < this.BASE_TIME {
   193  		return "20000101 00:00:00"
   194  	}
   195  	idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   196  	dtime := (int)((time - this.BASE_TIME) % MILLIS_PER_DAY)
   197  	hh := (int)(dtime / MILLIS_PER_HOUR)
   198  	dtime = (int)(dtime % MILLIS_PER_HOUR)
   199  	mm := (int)(dtime / MILLIS_PER_MINUTE)
   200  	dtime = (int)(dtime % MILLIS_PER_MINUTE)
   201  	ss := (int)(dtime / MILLIS_PER_SECOND)
   202  	sss := (int)(dtime % 1000)
   203  
   204  	var buffer bytes.Buffer
   205  	buffer.WriteString(this.dateTable[idx].date)
   206  	buffer.WriteString(" ")
   207  	buffer.WriteString(mk2(hh))
   208  	buffer.WriteString(":")
   209  	buffer.WriteString(mk2(mm))
   210  	buffer.WriteString(":")
   211  	buffer.WriteString(mk2(ss))
   212  	buffer.WriteString(".")
   213  	buffer.WriteString(mk2(sss))
   214  	return buffer.String()
   215  }
   216  func (this *DateTimeHelper) getDateMillis(time int64) int {
   217  	if time < this.BASE_TIME {
   218  		return 0
   219  	}
   220  	dtime := (time - this.BASE_TIME) % MILLIS_PER_DAY
   221  	return int(dtime)
   222  }
   223  func (this *DateTimeHelper) getDateStartTime(time int64) int64 {
   224  	if time < this.BASE_TIME {
   225  		return 0
   226  	}
   227  	dtime := (time - this.BASE_TIME) % MILLIS_PER_DAY
   228  	return time - dtime
   229  }
   230  func (this *DateTimeHelper) getHour(time int64) int {
   231  	return this.getDateMillis(time) / MILLIS_PER_HOUR
   232  }
   233  func (this *DateTimeHelper) getMM(time int64) int {
   234  	dtime := this.getDateMillis(time) % MILLIS_PER_HOUR
   235  	return (dtime / MILLIS_PER_MINUTE)
   236  }
   237  func (this *DateTimeHelper) getTimeUnit(time int64) int64 {
   238  	return (time - this.BASE_TIME)
   239  }
   240  func (this *DateTimeHelper) getDateUnit(time int64) int64 {
   241  	return (time - this.BASE_TIME) / MILLIS_PER_DAY
   242  }
   243  func (this *DateTimeHelper) getTenMinUnit(time int64) int64 {
   244  	return (time - this.BASE_TIME) / MILLIS_PER_TEN_MINUTE
   245  }
   246  func (this *DateTimeHelper) getFiveMinUnit(time int64) int64 {
   247  	return (time - this.BASE_TIME) / MILLIS_PER_FIVE_MINUTE
   248  }
   249  func (this *DateTimeHelper) getMinUnit(time int64) int64 {
   250  	return (time - this.BASE_TIME) / MILLIS_PER_MINUTE
   251  }
   252  func (this *DateTimeHelper) getHourUnit(time int64) int64 {
   253  	return (time - this.BASE_TIME) / MILLIS_PER_HOUR
   254  }
   255  func (this *DateTimeHelper) reverseHourUnit(unit int64) int64 {
   256  	return (unit * MILLIS_PER_HOUR) + this.BASE_TIME
   257  }
   258  func (this *DateTimeHelper) reverseUnit(unit int64, millis int64) int64 {
   259  	return (unit * millis) + this.BASE_TIME
   260  }
   261  
   262  func mk2(n int) string {
   263  	switch n {
   264  	case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
   265  		return "0" + strconv.Itoa(n)
   266  	}
   267  	return strconv.Itoa(n)
   268  }
   269  func mk3(n int) string {
   270  	switch n {
   271  	case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
   272  		return "00" + strconv.Itoa(n)
   273  	}
   274  	if n < 100 {
   275  		return "0" + strconv.Itoa(n)
   276  	} else {
   277  		return strconv.Itoa(n)
   278  	}
   279  }
   280  func (this *DateTimeHelper) ymdhms(time int64) string {
   281  	if time < this.BASE_TIME {
   282  		return "20000101000000"
   283  	}
   284  	idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   285  	dtime := (int)((time - this.BASE_TIME) % MILLIS_PER_DAY)
   286  	hh := (int)(dtime / MILLIS_PER_HOUR)
   287  	dtime = (int)(dtime % MILLIS_PER_HOUR)
   288  	mm := (int)(dtime / MILLIS_PER_MINUTE)
   289  	dtime = (int)(dtime % MILLIS_PER_MINUTE)
   290  	ss := (int)(dtime / MILLIS_PER_SECOND)
   291  	//sss := (int)(dtime % 1000)
   292  
   293  	var buffer bytes.Buffer
   294  	buffer.WriteString(this.dateTable[idx].date)
   295  	buffer.WriteString(mk2(hh))
   296  	buffer.WriteString(mk2(mm))
   297  	buffer.WriteString(mk2(ss))
   298  	return buffer.String()
   299  }
   300  func (this *DateTimeHelper) getYear(time int64, delta int) int64 {
   301  	if time < this.BASE_TIME {
   302  		return this.BASE_TIME
   303  	}
   304  	idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   305  	year := this.dateTable[idx].yyyy + delta
   306  	mm := this.dateTable[idx].mm
   307  	dd := this.dateTable[idx].dd
   308  	if year < 2000 {
   309  		return this.BASE_TIME
   310  	}
   311  	if year > 2100 {
   312  		return this.dateTable[this.LAST_DATE].time
   313  	}
   314  
   315  	dtime := (time - this.BASE_TIME) % MILLIS_PER_DAY
   316  
   317  	return this.table[year-2000][mm-1][dd-1].time + dtime
   318  }
   319  func (this *DateTimeHelper) getMonth(time int64, delta int) int64 {
   320  	if time < this.BASE_TIME {
   321  		return this.BASE_TIME
   322  	}
   323  	idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   324  	year := this.dateTable[idx].yyyy
   325  	mm := this.dateTable[idx].mm
   326  	dd := this.dateTable[idx].dd
   327  	delta = delta + mm - 1
   328  	deltaYear := delta / 12
   329  	deltaMM := delta % 12
   330  	if deltaMM < 0 {
   331  		deltaYear--
   332  		deltaMM = 12 + deltaMM
   333  	}
   334  	year += deltaYear
   335  	mm = deltaMM + 1
   336  	if year < 2000 {
   337  		return this.BASE_TIME
   338  	}
   339  	if year > 2100 {
   340  		return this.dateTable[this.LAST_DATE].time
   341  	}
   342  
   343  	dtime := (time - this.BASE_TIME) % MILLIS_PER_DAY
   344  	return this.table[year-2000][mm-1][dd-1].time + dtime
   345  }
   346  func (this *DateTimeHelper) getDate(time int64, delta int) int64 {
   347  	if time < this.BASE_TIME {
   348  		return this.BASE_TIME
   349  	}
   350  	idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   351  	dtime := (time - this.BASE_TIME) % MILLIS_PER_DAY
   352  	idx += delta
   353  	if idx < 0 {
   354  		return this.BASE_TIME
   355  	}
   356  	if idx >= this.LAST_DATE {
   357  		return this.dateTable[this.LAST_DATE].time
   358  	}
   359  	return this.dateTable[idx].time + dtime
   360  }
   361  func (this *DateTimeHelper) logtime(time int64) string {
   362  	if time < this.BASE_TIME {
   363  		return "00:00:00.000"
   364  	}
   365  	//idx := (int)((time - this.BASE_TIME) / MILLIS_PER_DAY)
   366  	dtime := (int)((time - this.BASE_TIME) % MILLIS_PER_DAY)
   367  	hh := (int)(dtime / MILLIS_PER_HOUR)
   368  	dtime = (int)(dtime % MILLIS_PER_HOUR)
   369  	mm := (int)(dtime / MILLIS_PER_MINUTE)
   370  	dtime = (int)(dtime % MILLIS_PER_MINUTE)
   371  	ss := (int)(dtime / MILLIS_PER_SECOND)
   372  	sss := (int)(dtime % 1000)
   373  
   374  	var buffer bytes.Buffer
   375  	buffer.WriteString(mk2(hh))
   376  	buffer.WriteString(":")
   377  	buffer.WriteString(mk2(mm))
   378  	buffer.WriteString(":")
   379  	buffer.WriteString(mk2(ss))
   380  	buffer.WriteString(".")
   381  	buffer.WriteString(mk2(sss))
   382  	return buffer.String()
   383  }
   384  func (this *DateTimeHelper) hhmmss(time int64) string {
   385  	if time < this.BASE_TIME {
   386  		return "000000"
   387  	}
   388  	dtime := (int)((time - this.BASE_TIME) % MILLIS_PER_DAY)
   389  	hh := (int)(dtime / MILLIS_PER_HOUR)
   390  	dtime = (int)(dtime % MILLIS_PER_HOUR)
   391  	mm := (int)(dtime / MILLIS_PER_MINUTE)
   392  	dtime = (int)(dtime % MILLIS_PER_MINUTE)
   393  	ss := (int)(dtime / MILLIS_PER_SECOND)
   394  	return fmt.Sprintf("%02d%02d%02d", hh, mm, ss)
   395  }
   396  func (this *DateTimeHelper) hhmm(time int64) string {
   397  	if time < this.BASE_TIME {
   398  		return "0000"
   399  	}
   400  	dtime := (int)((time - this.BASE_TIME) % MILLIS_PER_DAY)
   401  	hh := (int)(dtime / MILLIS_PER_HOUR)
   402  	dtime = (int)(dtime % MILLIS_PER_HOUR)
   403  	mm := (int)(dtime / MILLIS_PER_MINUTE)
   404  	return fmt.Sprintf("%02d%02d", hh, mm)
   405  }