go-hep.org/x/hep@v0.38.1/groot/rbase/datime.go (about)

     1  // Copyright ©2022 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rbase
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"time"
    11  
    12  	"go-hep.org/x/hep/groot/rbytes"
    13  	"go-hep.org/x/hep/groot/rtypes"
    14  	"go-hep.org/x/hep/groot/rvers"
    15  )
    16  
    17  // Datime is a ROOT date + time.
    18  // Note that ROOT's TDatime is relative to 1995.
    19  type Datime time.Time
    20  
    21  func (*Datime) Class() string {
    22  	return "TDatime"
    23  }
    24  
    25  func (*Datime) RVersion() int16 {
    26  	return rvers.Datime
    27  }
    28  
    29  // MarshalROOT implements rbytes.Marshaler
    30  func (dt *Datime) MarshalROOT(w *rbytes.WBuffer) (int, error) {
    31  	if w.Err() != nil {
    32  		return 0, w.Err()
    33  	}
    34  
    35  	// TDatime does not write a version header.
    36  	w.WriteU32(time2datime(time.Time(*dt)))
    37  
    38  	return 4, w.Err()
    39  }
    40  
    41  // UnmarshalROOT implements rbytes.Unmarshaler
    42  func (dt *Datime) UnmarshalROOT(r *rbytes.RBuffer) error {
    43  	if r.Err() != nil {
    44  		return r.Err()
    45  	}
    46  
    47  	// TDatime does not write a version header.
    48  	*dt = Datime(datime2time(r.ReadU32()))
    49  
    50  	return r.Err()
    51  }
    52  
    53  func (dt Datime) String() string {
    54  	return dt.Time().String()
    55  }
    56  
    57  func (dt Datime) Time() time.Time { return time.Time(dt) }
    58  
    59  func init() {
    60  	f := func() reflect.Value {
    61  		var o Datime
    62  		return reflect.ValueOf(&o)
    63  	}
    64  	rtypes.Factory.Add("TDatime", f)
    65  }
    66  
    67  // time2datime converts a time.Time to a uint32 representing a ROOT's TDatime.
    68  func time2datime(t time.Time) uint32 {
    69  	var (
    70  		year  = uint32(t.Year())
    71  		month = uint32(t.Month())
    72  		day   = uint32(t.Day())
    73  		hour  = uint32(t.Hour())
    74  		min   = uint32(t.Minute())
    75  		sec   = uint32(t.Second())
    76  	)
    77  
    78  	if year < 1995 {
    79  		panic(fmt.Errorf("rbase: TDatime year must be >= 1995"))
    80  	}
    81  
    82  	return (year-1995)<<26 | month<<22 | day<<17 | hour<<12 | min<<6 | sec
    83  }
    84  
    85  // datime2time converts a uint32 holding a ROOT's TDatime into a time.Time
    86  func datime2time(d uint32) time.Time {
    87  
    88  	// ROOT's TDatime begins in January 1995...
    89  	var year uint32 = (d >> 26) + 1995
    90  	var month uint32 = (d << 6) >> 28
    91  	var day uint32 = (d << 10) >> 27
    92  	var hour uint32 = (d << 15) >> 27
    93  	var min uint32 = (d << 20) >> 26
    94  	var sec uint32 = (d << 26) >> 26
    95  	nsec := 0
    96  	return time.Date(int(year), time.Month(month), int(day),
    97  		int(hour), int(min), int(sec), nsec, time.UTC)
    98  }