// since tar_time will only be second level precision, then when restoring the
// filepath from a tar_time, then compare the seconds first and only Chtimes if
// the seconds value is different.
483455
func tartimeUpdateKeywordFunc(path string, kv KeyVal) (os.FileInfo, error) {
	info, err := os.Lstat(path)
	if err != nil {
		return nil, err
	}

	v := strings.SplitN(kv.Value(), ".", 2)
	if len(v) != 2 {
		return nil, fmt.Errorf("expected a number like 1469104727.000000000")
	}
	sec, err := strconv.ParseInt(v[0], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("expected seconds, but got %q", v[0])
	}

	// if the seconds are the same, don't do anything, because the file might
	// have nanosecond value, and if using tar_time it would zero it out.
	if info.ModTime().Unix() == sec {
		return info, nil
	}

	vtime := time.Unix(sec, 0)

	// if times are same then don't modify anything
	// comparing Unix, since it does not include Nano seconds
	if info.ModTime().Unix() == vtime.Unix() {
		return info, nil
	}

	// symlinks are strange and most of the time passes through to the backing file
	if info.Mode()&os.ModeSymlink != 0 {
		if err := lchtimes(path, vtime, vtime); err != nil {
			return nil, err
		}
	} else if err := os.Chtimes(path, vtime, vtime); err != nil {
		return nil, err
	}
	return os.Lstat(path)
}
1282359
func (s *FileTime) Time() UTCTime {
	return UTCTime(time.Unix(int64(s.Convert()), 0))
}
535300
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
	f := (*syscall.Rusage)(first)
	l := (*syscall.Rusage)(latest)
	var (
		utimeDiffs  = l.Utime.Sec - f.Utime.Sec
		utimeDiffus = l.Utime.Usec - f.Utime.Usec
		stimeDiffs  = l.Stime.Sec - f.Stime.Sec
		stimeDiffus = l.Stime.Usec - f.Stime.Usec
	)

	uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
	sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6

	return uTimeElapsed, sTimeElapsed
}
100188
func TimeToTimespec(time time.Time) (ts syscall.Timespec) {
	nsec := int64(0)
	if !time.IsZero() {
		nsec = time.UnixNano()
	}
	return syscall.NsecToTimespec(nsec)
}
1322062
func CompactInterval(seconds int) FileStoreOption {
	return func(o *FileStoreOptions) error {
		if seconds <= 0 {
			return fmt.Errorf("compact interval value must at least be 1 seconds")
		}
		o.CompactInterval = seconds
		return nil
	}
}
722607
func ConvertToTimestamp(timeString string) *Timestamp {
	parsed, _ := time.Parse(time.RFC3339Nano, timeString)
	return &Timestamp{parsed}
}
1327929
func RepoModTime(dir string) (time.Time, error) {
	var last time.Time
	refDir := filepath.Join(dir, "refs")
	if _, err := os.Lstat(refDir); err == nil {
		if err := filepath.Walk(refDir,
			func(name string, fi os.FileInfo, err error) error {
				if !fi.IsDir() && last.Before(fi.ModTime()) {
					last = fi.ModTime()
				}
				return nil
			}); err != nil {
			return last, err
		}
	}

	// git gc compresses refs into the following file:
	for _, fn := range []string{"info/refs", "packed-refs"} {
		if fi, err := os.Lstat(filepath.Join(dir, fn)); err == nil && !fi.IsDir() && last.Before(fi.ModTime()) {
			last = fi.ModTime()
		}
	}

	return last, nil
}
326618
func TimestampParse(s string) (Timestamp, error) {
	layout := "2006-01-02T15:04:05.999Z"
	t, e := time.Parse(layout, s)
	if e != nil {
		if strings.HasSuffix(s, "+00:00") || strings.HasSuffix(s, "-00:00") {
			t, e = time.Parse(layout, s[:len(s)-6]+"Z")
		} else if strings.HasSuffix(s, "+0000") || strings.HasSuffix(s, "-0000") {
			t, e = time.Parse(layout, s[:len(s)-5]+"Z")
		}
		if e != nil {
			var ts Timestamp
			return ts, e
		}
	}
	return Timestamp{t}, nil
}
726187
func TimestampLess(i *timestamp.Timestamp, j *timestamp.Timestamp) bool {
	if j == nil {
		return false
	}
	if i == nil {
		return true
	}
	if i.Seconds < j.Seconds {
		return true
	}
	if i.Seconds > j.Seconds {
		return false
	}
	return i.Nanos < j.Nanos
}
807497
func TimeSincePro(then time.Time) string {
	now := time.Now()
	diff := now.Unix() - then.Unix()

	if then.After(now) {
		return "future"
	}

	var timeStr, diffStr string
	for {
		if diff == 0 {
			break
		}

		diff, diffStr = computeTimeDiff(diff)
		timeStr += ", " + diffStr
	}
	return strings.TrimPrefix(timeStr, ", ")
}
1102003
func LoadFileTime(path string) (FileTime, error) {
	var ft = FileTime{}
	var st = unix.Stat_t{}

	err := unix.Stat(path, &st)
	if err != nil {
		return ft, err
	}

	ft.Changed = timeSpecToTime(st.Ctim)
	ft.Modified = timeSpecToTime(st.Mtim)
	ft.Accessed = timeSpecToTime(st.Atim)
	return ft, nil
}
1350645
func GetFileModTime(path string) int64 {
	path = strings.Replace(path, "\\", "/", -1)
	f, err := os.Open(path)
	if err != nil {
		beeLogger.Log.Errorf("Failed to open file on '%s': %s", path, err)
		return time.Now().Unix()
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		beeLogger.Log.Errorf("Failed to get file stats: %s", err)
		return time.Now().Unix()
	}

	return fi.ModTime().Unix()
}
2488
func durationToTimespec(d time.Duration) unix.Timespec {
	return unix.NsecToTimespec(d.Nanoseconds())
}
1129367
func chtimes(path string, atime, mtime time.Time) error {
	ctimespec := windows.NsecToTimespec(mtime.UnixNano())
	pathp, e := windows.UTF16PtrFromString(path)
	if e != nil {
		return e
	}
	h, e := windows.CreateFile(pathp,
		windows.FILE_WRITE_ATTRIBUTES, windows.FILE_SHARE_WRITE, nil,
		windows.OPEN_EXISTING, windows.FILE_FLAG_BACKUP_SEMANTICS, 0)
	if e != nil {
		return e
	}
	defer windows.Close(h)
	c := windows.NsecToFiletime(windows.TimespecToNsec(ctimespec))
	return windows.SetFileTime(h, &c, nil, nil)
}
86287
func Tar(path string, compression Compression) (io.ReadCloser, error) {
	return TarWithOptions(path, &TarOptions{Compression: compression})
}
319576
func parseFileTime(filename string) (time.Time, error) {
	base := strings.TrimSuffix(filename, filepath.Ext(filename))
	return time.Parse(defaults.AuditLogTimeFormat, base)
}
985567
func readFileTimestamp(p string) (time.Time, error) {
	b, err := ioutil.ReadFile(p)
	if err != nil {
		if os.IsNotExist(err) {
			err = errors.Wrap(errdefs.ErrNotFound, err.Error())
		}
		return time.Time{}, err
	}

	var t time.Time
	if err := t.UnmarshalText(b); err != nil {
		return time.Time{}, errors.Wrapf(err, "could not parse timestamp file %v", p)
	}

	return t, nil
}