How do you deal with wall-clock times without date in Go?

huangapple go评论93阅读模式
英文:

How do you deal with wall-clock times without date in Go?

问题

我想知道在Golang中是否有任何现有的包可以处理没有日期的日期时间。

问题如下。想象一下,我想要存储有关公司班次的信息,包括班次的开始和结束时间,我会创建类似于以下的内容:

import "time"

type Shift struct {
    StartTime  time.Time
    FinishTime time.Time
    // 更多字段
}

问题是,time.Time字段还存储有关日期、月份和年份的信息,这可能会在比较班次时导致几个问题。

是否有任何替代方案,类似于civil.Date(https://pkg.go.dev/cloud.google.com/go/civil),但只针对时间而不是日期?

英文:

I'd like to know if there is any existing package to deal with datetimes without date in Golang.

The problem is as follows. Imagine I want to store information about shifts in a company, including when this shifts start and end, I would create something like:

import "time"

type Shift struct {
    StartTime  time.Time
    FinishTime time.Time
    // More fields
}

The problem is, the field time.Time also stores information about the day, month and year, and that could lead to several problems at the time of comparing shifts.

Is there any alternative like civil.Date (https://pkg.go.dev/cloud.google.com/go/civil) but for just times instead of just dates?

答案1

得分: 3

time.Duration可以用于表示没有日期的墙钟时间。以下是一些示例:

type Shift struct {
	StartTime  time.Duration
	FinishTime time.Duration
}

func main() {
	d1, _ := time.ParseDuration("11h")  // 11:00
	d2, _ := time.ParseDuration("20h")  // 20:00
	shift := Shift{
		StartTime:  d1,
		FinishTime: d2,
	}

	// 如果你想将它们放在特定的一天
	today0 := time.Now().UTC().Truncate(24 * time.Hour)

	start := today0.Add(shift.StartTime)
	finish := today0.Add(shift.FinishTime)

	fmt.Printf("开始时间:%v\n结束时间:%v\n", start, finish)
}

对于跨越两天的时间:

d1, _ := time.ParseDuration("-30m")   // 前一天的23:30
d2, _ := time.ParseDuration("6h30m")  // 后一天的6:30
英文:

time.Duration can be used for wall-clock time without date. Some examples:

type Shift struct {
	StartTime  time.Duration
	FinishTime time.Duration
}

func main() {
	d1, _ := time.ParseDuration("11h")  // 11:00
	d2, _ := time.ParseDuration("20h")  // 20:00
	shift := Shift{
		StartTime:  d1,
		FinishTime: d2,
	}

	// If you want to put them into specific day
	today0 := time.Now().UTC().Truncate(24 * time.Hour)

	start := today0.Add(shift.StartTime)
	finish := today0.Add(shift.FinishTime)

	fmt.Printf("Start at: %v\nFinish at: %v\n", start, finish)
}

For times that span two days:

d1, _ := time.ParseDuration("-30m")   // 23:30 of previous day
d2, _ := time.ParseDuration("6h30m")  // 6:30 of next day

答案2

得分: 2

为了仅获取时间并省略有关日期、月份和年份的其他信息,您可以使用Format()方法。我已经为此创建了一个示例程序,如下所示:

package main

import (
	"fmt"
	"time"
)

func main() {

	const (
		layoutTime = "15:04:05"
	)

	fmt.Println("日期", time.Now())
	fmt.Println("时间", time.Now().Format(layoutTime))

}

输出结果:

日期 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
时间 23:00:00

请注意,这是一个Go语言的示例程序,用于获取当前日期和时间,并将时间格式化为只包含小时、分钟和秒的格式。

英文:

In order to have just time and omit the other information about the day, month and year you can make use of Format() method. I have created a sample program for the same as follows:

package main

import (
	"fmt"
	"time"
)

func main() {

	const (
		layoutTime = "15:04:05"
	)

	fmt.Println("Date", time.Now())
	fmt.Println("Time", time.Now().Format(layoutTime))

}

Output:

Date 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
Time 23:00:00

答案3

得分: 1

相信我,你仍然需要日期,而不仅仅是时间。

例如:如果StartTime = 23:00:00FinishTime = 06:00:00,如果你没有捕获日期,那么Shift结构体内的信息就是FinishTime < StartTime,这与startfinish本身的含义相悖。

这就是日期的作用所在,所以如果FinishTime大于StartTime,那么StartTime需要减去一天,或者FinishTime加上一天。

以下是我编写的示例解决方案代码,用于检查currentTime是否在两个时间(时钟)之间:

首先,由于我只需要时钟信息(HH:mm:ss),我更喜欢使用string类型来表示StartTimeFinishTime

type Shift struct {
	StartTime  string
	FinishTime string
}

以下是代码示例:

type Shift struct {
	StartTime  string
	FinishTime string
}

func main() {
	myShift := Shift{
		StartTime:  "23:00",
		FinishTime: "06:00",
	}
	actualStartTime, actualEndTime := convertShiftClockToShiftTime(myShift.StartTime, myShift.FinishTime)
	fmt.Println(actualStartTime, actualEndTime)
}

func convertShiftClockToShiftTime(StartTime string, FinishTime string) (startTime time.Time, endTime time.Time) {

	// 我需要将时间转换为字符串,以便可以轻松地添加时钟
	timeLayout := "2006-01-02T15:04"
	dateOnlyLayout := "2006-01-02"

	currentTime := time.Now()
	currentDate := currentTime.Format(dateOnlyLayout)
	// currentDate = Y-m-d

	startDateStr := currentDate + "T" + StartTime
	startTime, _ = time.Parse(timeLayout, startDateStr)

	endDateStr := currentDate + "T" + FinishTime
	endTime, _ = time.Parse(timeLayout, endDateStr)

	if startTime.After(endTime) {
		// 如果endTime < startTime,则将endTime加上1天
		endTime = endTime.AddDate(0, 0, 1)
	}

	return startTime, endTime
}

我创建了一个名为convertShiftClockToShiftTime的函数,将时钟转换为实际时间,就像我之前提到的,如果StartTime = 23:00EndTime = 06:00

基本上,程序应该知道如果StartTime大于FinishTime,FinishTime应该是明天。

希望这可以帮助你,我希望我的解释能够解释清楚time本身的含义。

英文:

Trust me, You still need the Date, not just the Clock.

For example : what if the StartTime = 23:00:00 and FinishTime = 06:00:00, if you didn't capture the date, the information inside of the Shift struct is FinishTime &lt; StartTime, and that goes against the words of start and finish itself.

That's where the date works, so if the FinishTime is more than the StartTime, the StartTime needs to be reduced by 1 day OR FinishTime plus 1 day.

Here's the example solution code that I make to check if the currentTime is between 2 time(clock)

First of all since I just need the clock information (HH:mm:ss), I prefer to use a string type for the StartTime and FinishTime.

type Shift struct {
	StartTime  string
	FinishTime string
}

and here's what it goes.


type Shift struct {
	StartTime  string
	FinishTime string
}

func main() {
	myShift := Shift{
		StartTime:  &quot;23:00&quot;,
		FinishTime: &quot;06:00&quot;,
	}
	actualStartTime, actualEndTIme := convertShiftClockToShiftTime(myShift.StartTime, myShift.FinishTime)
	fmt.Println(actualStartTime, actualEndTIme)
}

func convertShiftClockToShiftTime(StartTime string, FinishTime string) (startTime time.Time, endTime time.Time) {

	// I need to convert the time to a string so I can easily add the clock
	timeLayout := &quot;2006-01-02T15:04&quot;
	dateOnlyLayout := &quot;2006-01-02&quot;

	currentTime := time.Now()
	currentDate := currentTime.Format(dateOnlyLayout)
	// currentDate = Y-m-d

	startDateStr := currentDate + &quot;T&quot; + StartTime
	startTime, _ = time.Parse(timeLayout, startDateStr)

	endDateStr := currentDate + &quot;T&quot; + FinishTime
	endTime, _ = time.Parse(timeLayout, endDateStr)

	if startTime.After(endTime) {
		// plus 1 day to the endTime if the endTime &lt; startTime
		endTime = endTime.AddDate(0, 0, 1)
	}

	return startTime, endTime
}

I created a function called convertShiftClockToShiftTime to change the clock into actual time as I mentioned before, what if the StartTime = 23:00 and EndTime = 06:00.

Basically the program should know if the StartTime is more than FinishTime, FinishTime should be tomorrow.

Hope this helps, I hope my explanation can explain to you what time itself means.

答案4

得分: 0

这个问题有点难回答,因为你并没有详细描述这个类型需要做什么,除了这个:

> 是的,但关键是,如果允许用户提供日期,那么time.Time在小于/大于比较中容易出现错误。目标应该是拥有一个可比较的结构体,用户不提供日期以避免混乱。

基于此,你可以使用类似以下的代码:

package wall
import "errors"

type Clock struct { hour, minute, second int }

func NewClock(h, m, s int) (*Clock, error) {
   if h > 23 || m > 59 || s > 59 {
      return nil, errors.New("无效的输入")
   }
   return &Clock{h, m, s}, nil
}

func (c Clock) Seconds() int {
   return c.hour * 60 * 60 + c.minute * 60 + c.second
}

func (c Clock) LessThan(d *Clock) bool {
   return c.Seconds() < d.Seconds()
}

示例:

package main
import "wall"

func main() {
   c, err := wall.NewClock(9, 59, 59)
   if err != nil {
      panic(err)
   }
   d, err := wall.NewClock(10, 59, 59)
   if err != nil {
      panic(err)
   }
   println(c.LessThan(d))
}
英文:

It's kind of hard to answer this question, as you haven't really described what the type would need to do, other than this:

> Yeah, but the point is, that time.Time will be prone to bugs in a less-than /
> more-than comparison if you allow the user to give a date. The goal should be
> to have a comparable struct and for the user not to give a date in order not
> to mess it up.

So going off that, you could use something like this:

package wall
import &quot;errors&quot;

type Clock struct { hour, minute, second int }

func NewClock(h, m, s int) (*Clock, error) {
   if h &gt; 23 || m &gt; 59 || s &gt; 59 {
      return nil, errors.New(&quot;invalid input&quot;)
   }
   return &amp;Clock{h, m, s}, nil
}

func (c Clock) Seconds() int {
   return c.hour * 60 * 60 + c.minute * 60 + c.second
}

func (c Clock) LessThan(d *Clock) bool {
   return c.Seconds() &lt; d.Seconds()
}

Example:

package main
import &quot;wall&quot;

func main() {
   c, err := wall.NewClock(9, 59, 59)
   if err != nil {
      panic(err)
   }
   d, err := wall.NewClock(10, 59, 59)
   if err != nil {
      panic(err)
   }
   println(c.LessThan(d))
}

huangapple
  • 本文由 发表于 2021年6月22日 17:38:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/68081142.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定