package main import ( "fmt" "os" "sophuwu.site/byterate" "strings" "time" ) type inputs struct { nums []string help bool dur bool time bool } func parseArgs(args []string) (i inputs, err error) { opts := "" for _, arg := range args { if strings.HasPrefix(arg, "--") { opts += arg[2:3] } else if strings.HasPrefix(arg, "-") { opts += arg[1:] } else { i.nums = append(i.nums, arg) } } for _, opt := range opts { switch opt { case 'h': i.help = true case 'd': i.dur = true case 't': i.time = true } } if !i.dur && !i.time { i.dur = true } if len(i.nums) != 2 { err = fmt.Errorf("expected 2 arguments, got %d", len(i.nums)) } return } func tailS(n int) string { if n == 1 { return "" } return "s" } func main() { var ( s, r byterate.Size t time.Time d time.Duration i inputs err error prnt string ) i, err = parseArgs(os.Args[1:]) if i.help { fmt.Println(strings.ReplaceAll(helpText, "{{ name }}", os.Args[0])) return } if err != nil { goto bad } s, err = byterate.ParseSize(i.nums[0]) if err != nil { goto bad } r, err = byterate.ParseSize(i.nums[1]) if err != nil { goto bad } t, d, err = byterate.Time(s, r) if err != nil { goto bad } if i.dur { if d.Hours() > 23 { days := int(d.Hours() / 24) if days > 365 { years := days / 365 prnt = fmt.Sprintf("%d year%s, ", years, tailS(years)) days %= 365 } hrs := int(d.Hours()) % 24 prnt += fmt.Sprintf("%d day%s, %02d hour%s, ", days, tailS(days), hrs, tailS(hrs)) } else if d.Hours() >= 1 { prnt = fmt.Sprintf("%02d hour%s, ", int(d.Hours()), tailS(int(d.Hours()))) } mins := int(d.Minutes()) % 60 if prnt != "" || mins > 0 { prnt += fmt.Sprintf("%02d minute%s and ", mins, tailS(mins)) } secs := int(d.Seconds()) % 60 prnt += fmt.Sprintf("%02d second%s", secs, tailS(secs)) fmt.Println(prnt) } if i.time { prnt = "Today " ndate := time.Now().Truncate(time.Hour * 24) tdate := t.Truncate(time.Hour * 24) if !tdate.Equal(ndate) { if tdate.Equal(ndate.AddDate(0, 0, 1)) { prnt = "Tomorrow " } else if t.Before(ndate.AddDate(0, 0, 6)) { prnt = t.Weekday().String() + " at " + prnt } else if t.Year() == ndate.Year() { prnt = "02 Jan " } else { prnt = "02 Jan 2006 " } } fmt.Println(t.Format(prnt + "15:04")) } return bad: fmt.Printf("Usage: %s \n", os.Args[0]) fmt.Println("\t--help for more information") } const helpText = `{{ name }}: Print the time it takes to transfer a file at a given rate. Usage: {{ name }} [options] Options: -h --help Show this help message. -d --duration Print the duration the transfer will take. -t --time Print the time the transfer will finish if started now. if no options are given, duration will be printed. is the size of the file to transfer. is the transfer rate as a size, always per second. SI prefixes are supported (e.g. 1k = 1000, 1ki = 1024) Supported units are: b for bytes, bit for bits. If no unit is given, bytes are assumed. Examples: 10 GiB at 120 mbps : {{ name }} 10gib 120mbit 16 MiB at 1.2 MiB/s: {{ name }} 16mib 1.2mib 15 GB at 1.5 MB/s : {{ name }} 1.5g 1.5m `