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

     1  package dateutil
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"strconv"
     8  	"time"
     9  )
    10  
    11  const (
    12  	DATEFORMAT_YEAR        = 'y'
    13  	DATEFORMAT_MONTH       = 'm'
    14  	DATEFORMAT_DAY         = 'd'
    15  	DATEFORMAT_HOUR        = 'H'
    16  	DATEFORMAT_MINUTE      = 'M'
    17  	DATEFORMAT_SECOND      = 'S'
    18  	DATEFORMAT_MILLISECOND = 's'
    19  )
    20  
    21  type DateFormat struct {
    22  	formatStr []rune
    23  	dateStr   string
    24  	date      map[rune]int
    25  }
    26  
    27  func NewDateFormat(formatStr string) *DateFormat {
    28  	p := new(DateFormat)
    29  	p.formatStr = []rune(formatStr)
    30  	p.date = make(map[rune]int)
    31  	return p
    32  }
    33  
    34  func (this *DateFormat) Format() string {
    35  	return this.format(time.Now())
    36  }
    37  func (this *DateFormat) FormatTime(t time.Time) string {
    38  	return this.format(t)
    39  }
    40  
    41  func (this *DateFormat) format(t time.Time) string {
    42  	ret := this.formatStr
    43  	var buf bytes.Buffer
    44  	for _, ch := range ret {
    45  		switch ch {
    46  		case DATEFORMAT_YEAR:
    47  			buf.WriteString(LPadInt(t.Year(), 4))
    48  		case DATEFORMAT_MONTH:
    49  			buf.WriteString(LPadInt(int(t.Month()), 2))
    50  		case DATEFORMAT_DAY:
    51  			buf.WriteString(LPadInt(t.Day(), 2))
    52  		case DATEFORMAT_HOUR:
    53  			buf.WriteString(LPadInt(t.Hour(), 2))
    54  		case DATEFORMAT_MINUTE:
    55  			buf.WriteString(LPadInt(t.Minute(), 2))
    56  		case DATEFORMAT_SECOND:
    57  			buf.WriteString(LPadInt(t.Second(), 2))
    58  		case DATEFORMAT_MILLISECOND:
    59  			buf.WriteString(LPadInt(int((t.UnixNano()/1000000)%1000), 3))
    60  		default:
    61  			buf.WriteRune(ch)
    62  		}
    63  	}
    64  	return buf.String()
    65  }
    66  
    67  func (this *DateFormat) Parse(dateStr string) (int64, error) {
    68  	r := bytes.NewReader([]byte(dateStr))
    69  	sz := len(dateStr)
    70  	now := time.Now()
    71  	for i, ch := range this.formatStr {
    72  		if i >= sz {
    73  			break
    74  		}
    75  		switch ch {
    76  		case DATEFORMAT_YEAR:
    77  			if v, err := this.ToInt(r, 4); err == nil {
    78  				this.date[ch] = v
    79  			} else {
    80  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
    81  			}
    82  		case DATEFORMAT_MONTH:
    83  			if v, err := this.ToInt(r, 2); err == nil {
    84  				this.date[ch] = v
    85  			} else {
    86  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
    87  			}
    88  		case DATEFORMAT_DAY:
    89  			if v, err := this.ToInt(r, 2); err == nil {
    90  				this.date[ch] = v
    91  			} else {
    92  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
    93  			}
    94  		case DATEFORMAT_HOUR:
    95  			if v, err := this.ToInt(r, 2); err == nil {
    96  				this.date[ch] = v
    97  			} else {
    98  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
    99  			}
   100  		case DATEFORMAT_MINUTE:
   101  			if v, err := this.ToInt(r, 2); err == nil {
   102  				this.date[ch] = v
   103  			} else {
   104  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
   105  			}
   106  		case DATEFORMAT_SECOND:
   107  			if v, err := this.ToInt(r, 2); err == nil {
   108  				this.date[ch] = v
   109  			} else {
   110  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
   111  			}
   112  		case DATEFORMAT_MILLISECOND:
   113  			if v, err := this.ToInt(r, 3); err == nil {
   114  				this.date[ch] = v
   115  			} else {
   116  				return 0, fmt.Errorf("Parse error ch=%s, err=%s ", string(ch), err)
   117  			}
   118  		default:
   119  			r.ReadRune()
   120  		}
   121  	}
   122  
   123  	// format에 없는 경우, 현재 시간 기준
   124  	if _, ok := this.date[DATEFORMAT_YEAR]; !ok {
   125  		this.date[DATEFORMAT_YEAR] = now.Year()
   126  	}
   127  	if _, ok := this.date[DATEFORMAT_MONTH]; !ok {
   128  		this.date[DATEFORMAT_MONTH] = int(now.Month())
   129  	}
   130  	if _, ok := this.date[DATEFORMAT_DAY]; !ok {
   131  		this.date[DATEFORMAT_DAY] = now.Day()
   132  	}
   133  	if _, ok := this.date[DATEFORMAT_HOUR]; !ok {
   134  		this.date[DATEFORMAT_HOUR] = now.Hour()
   135  	}
   136  	if _, ok := this.date[DATEFORMAT_MINUTE]; !ok {
   137  		this.date[DATEFORMAT_MINUTE] = now.Minute()
   138  	}
   139  	if _, ok := this.date[DATEFORMAT_SECOND]; !ok {
   140  		this.date[DATEFORMAT_SECOND] = now.Second()
   141  	}
   142  	if _, ok := this.date[DATEFORMAT_MILLISECOND]; !ok {
   143  		this.date[DATEFORMAT_MILLISECOND] = int(now.UnixNano() / 1000000 % 1000)
   144  	}
   145  
   146  	d := time.Date(this.date[DATEFORMAT_YEAR], time.Month(this.date[DATEFORMAT_MONTH]), this.date[DATEFORMAT_DAY], this.date[DATEFORMAT_HOUR],
   147  		this.date[DATEFORMAT_MINUTE], this.date[DATEFORMAT_SECOND], this.date[DATEFORMAT_MILLISECOND]*1000000, time.Now().Location())
   148  	tm := d.UnixNano() / 1000000
   149  	return tm, nil
   150  }
   151  
   152  func (this *DateFormat) ToInt(rd *bytes.Reader, size int) (int, error) {
   153  	buf := make([]byte, size)
   154  	if n, err := rd.Read(buf); err != nil {
   155  		if err == io.EOF {
   156  			return 0, nil
   157  		}
   158  		return 0, err
   159  	} else {
   160  		if n != size {
   161  			return 0, fmt.Errorf("Error read size, want=%d, have=%d", size, n)
   162  		}
   163  	}
   164  
   165  	if v, err := strconv.Atoi(string(buf)); err != nil {
   166  		return 0, err
   167  	} else {
   168  		return v, nil
   169  	}
   170  }
   171  
   172  func padding(n int, ch string) string {
   173  	buf := bytes.Buffer{}
   174  	for i := 0; i < n; i++ {
   175  		buf.WriteString(ch)
   176  	}
   177  	return buf.String()
   178  }
   179  
   180  func LPadInt(v, size int) string {
   181  	var ret string
   182  	ret = fmt.Sprintf("%d", v)
   183  	if len(ret) > size {
   184  		return ret
   185  	}
   186  	return padding(size-len(ret), "0") + ret
   187  }