golang时间。因为()有几个月和几年 [英] golang time.Since() with months and years

查看:221
本文介绍了golang时间。因为()有几个月和几年的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图转换一个这样的时间戳:

  2015-06-27T09:34:22 + 00:00 

到格式化的时间,所以它会像9个月前那样说1天2小时30分2秒。

类似的东西。



我用 time.Parse time.Since 以达到此目的:

  6915h7m47 .6901559s 

但我该如何转换?像这样的东西就是我的想法:

 小时> 24 {
天++
小时 - = 24
}

但问题在于这个月的数据可能会有28天,30天和31天的不准确的情况。



有没有更好的方法来实现我想要的?

解决方案

一个月中的日子取决于日期,就像一年中的日子一样(闰年) p>

如果您使用 时间。从() 获取自 time.Time 值,或者当您计算2 time.Time 值之间的差值时,使用 Time.Sub() 方法,结果是 time.Duration ,其中输时间上下文(如持续时间只是时间差(纳秒))。这意味着您无法准确无误地计算年持续时间值的年,月等差异。



正确的解决方案必须计算时间背景下的差异。您可以计算每个字段(年,月,日,小时,分钟,秒)的差异,然后将结果标准化为不含任何负值。如果它们之间的关系不是预期的,建议交换 Time 值。



标准化意味着if例如,如果为负值,则添加 60 值为负,添加该字段的最大值并将下一个字段递减1。 code>>并将分钟减1。有一点需要注意的是,将日期差异(月份中的天数),日期正确的月份必须适用。这可以很容易地用这个小技巧计算出来:

  // y1,M1月份的最大天数
t:= time.Date(y1,M1,32,0,0,0,time.UTC)
daysInMonth:= 32 - t.Day()

这背后的逻辑是,每天 32 大于任何月份的最大日期。它会被自动标准化(额外的日子被推迟到下一个月,并且日子正常地减少)。当我们减去32天的标准化后的日数时,我们得到的确实是该月的最后一天。



时区处理:



如果我们传入的两个时间值都位于同一时区( time.Location )。我们在我们的功能中加入了一张支票:如果情况并非如此,我们使用 Time.In() 方法:



<如果a.Location()!= b.Location(){
b = b.In(a.Location())
}
/ code>

以下是计算年,月,日,小时,分钟,秒差异的解决方案:

  func diff(a,b time.Time)(year,month,day,hour,min,sec int){$如果a.Location()!= b.Location(){
b = b.In(a.Location())
}
如果a.After(b){
a,b = b,a
}
y1,M1,d1:= a.Date()
y2,M2,d2:= b.Date()

h1,m1,s1:= a.Clock()
h2,m2,s2:= b.Clock()

年= int(y2 - y1)
月= int(M2 - M1)
日= int(d2 - d1)
小时= int(h2 - h1)
m in = int(m2 - m1)
sec = int(s2 - s1)

//标准化负值
if sec< 0 {
sec + = 60
min--
}
如果min < 0 {
分钟+ = 60
小时 -
}
如果小时< 0 {
小时+ = 24
天 -
}
如果天< 0 {
//月中的天数:
t:= time.Date(y1,M1,32,0,0,0,time.UTC)
day + = 32 - t .Day()
月 -
}
如果月份< 0 {
month + = 12
year--
}

return
}

一些测试:

  var a,b time.Time 
a = time.Date(2015,5,1,0,0,0,0,time.UTC)
b = time.Date(2016,6,2,1,1,1,1,time .UTC)
fmt.Println(diff(a,b))//预期:1 1 1 1 1 1

a = time.Date(2016,1,2,0,0 ,0,0,time.UTC)
b = time.Date(2016,2,1,0,0,0,time.UTC)
fmt.Println(diff(a,b) )//预期:0 0 30 0 0 0

a = time.Date(2016,2,2,0,0,0,time.UTC)
b = time.Date (2016,3,1,0,0,0,time.UTC)
fmt.Println(diff(a,b))//预期:0 0 28 0 0 0

a = time.Date(2015,2,11,0,0,0,0,time.UTC)
b = time.Date(2016,1,12,0,0,0,0,time。 UTC)
fmt.Println(diff(a,b))//预期:0 11 1 0 0 0

产量如预期:

  1 1 1 1 1 1 
0 0 30 0 0 0
0 0 28 0 0 0
0 11 1 0 0 0

试试

 

//你的生日:假设它是1980年1月2日,3:30 AM
生日:= time.Date(1980,1,2,3,30,0,0,时间。 UTC)
年,月,日,小时,分钟,秒:= diff(生日,time.Now())

fmt.Printf(你是%d年,%d月,%d天,%d小时,%d分钟和%d秒以前。,
年,月,日,小时,分钟,秒)
pre>

示例输出:

 您是36岁3个月,8天,11小时,57分钟和41秒。 

Go游乐场时间开始的神奇日期/时间为: 2009 -11-10 23:00:00 UTC

这是Go第一次宣布的时间。让我们来计算Go的年龄:

  goAnnounced:= time.Date(2009,11,10,23,0,0, 0,time.UTC)
year,month,day,hour,min,sec:= diff(goAnnounced,time.Now())
fmt.Printf(Go was released+
%d年,%d个月,%d日,%d小时,%d分钟和%d秒前,
年,月,日,小时,分钟,秒)

输出:

  Go在6年,4个月,29天,16小时,53分钟和31秒前宣布。 


I am trying to convert a timestamp like this:

2015-06-27T09:34:22+00:00

to a time since format so it would say like 9 months ago 1 day 2 hours 30 minutes 2 seconds.

something like that.

I used time.Parse and time.Since to get to this:

6915h7m47.6901559s

But how do I convert from there on? Something like this is what I thought:

for hours > 24 {
        days++
        hours -= 24
}

But the issue with this is that this won't be accurate for months because months can have 28, 30 and 31 days.

Is there a better way of achieving what I want?

解决方案

The days in a month depends on the date, just like the days in a year (leap years).

If you use time.Since() to get the elapsed time since a time.Time value, or when you calculate the difference between 2 time.Time values using the Time.Sub() method, the result is a time.Duration which loses the time context (as Duration is just the time difference in nanoseconds). This means you cannot accurately and unambiguously calculate the difference in years, months, etc. from a Duration value.

The right solution must calculate the difference in the context of the time. You may calculate the difference for each field (year, month, day, hour, minute, second), and then normalize the result to not have any negative values. It is also recommended to swap the Time values if the relation between them is not the expected.

Normalization means if a value is negative, add the maximum value of that field and decrement the next field by 1. For example if seconds is negative, add 60 to it and decrement minutes by 1. One thing to look out for is when normalizing the difference of days (days in month), the number of days in the proper month has to be applied. This can easily be calculated with this little trick:

// Max days in year y1, month M1
t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC)
daysInMonth := 32 - t.Day()

The logic behind this is that the day 32 is bigger than the max day in any month. It will get automatically normalized (extra days rolled to the next month and day decremented properly). And when we subtract day we have after normalization from 32, we get exactly what the last day was in the month.

Time zone handling:

The difference calculation will only give correct result if both of the time values we pass in are in the same time zone (time.Location). We incorporate a check into our function: if this is not the case, we "convert" one of the time value to be in the same location as the other using the Time.In() method:

if a.Location() != b.Location() {
    b = b.In(a.Location())
}

Here's a solution which calculates difference in year, month, day, hour, min, sec:

func diff(a, b time.Time) (year, month, day, hour, min, sec int) {
    if a.Location() != b.Location() {
        b = b.In(a.Location())
    }
    if a.After(b) {
        a, b = b, a
    }
    y1, M1, d1 := a.Date()
    y2, M2, d2 := b.Date()

    h1, m1, s1 := a.Clock()
    h2, m2, s2 := b.Clock()

    year = int(y2 - y1)
    month = int(M2 - M1)
    day = int(d2 - d1)
    hour = int(h2 - h1)
    min = int(m2 - m1)
    sec = int(s2 - s1)

    // Normalize negative values
    if sec < 0 {
        sec += 60
        min--
    }
    if min < 0 {
        min += 60
        hour--
    }
    if hour < 0 {
        hour += 24
        day--
    }
    if day < 0 {
        // days in month:
        t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC)
        day += 32 - t.Day()
        month--
    }
    if month < 0 {
        month += 12
        year--
    }

    return
}

Some tests:

var a, b time.Time
a = time.Date(2015, 5, 1, 0, 0, 0, 0, time.UTC)
b = time.Date(2016, 6, 2, 1, 1, 1, 1, time.UTC)
fmt.Println(diff(a, b)) // Expected: 1 1 1 1 1 1

a = time.Date(2016, 1, 2, 0, 0, 0, 0, time.UTC)
b = time.Date(2016, 2, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(diff(a, b)) // Expected: 0 0 30 0 0 0

a = time.Date(2016, 2, 2, 0, 0, 0, 0, time.UTC)
b = time.Date(2016, 3, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(diff(a, b)) // Expected: 0 0 28 0 0 0

a = time.Date(2015, 2, 11, 0, 0, 0, 0, time.UTC)
b = time.Date(2016, 1, 12, 0, 0, 0, 0, time.UTC)
fmt.Println(diff(a, b)) // Expected: 0 11 1 0 0 0

Output is as expected:

1 1 1 1 1 1
0 0 30 0 0 0
0 0 28 0 0 0
0 11 1 0 0 0

Try it on the Go Playground.

To calculate how old you are:

// Your birthday: let's say it's January 2nd, 1980, 3:30 AM
birthday := time.Date(1980, 1, 2, 3, 30, 0, 0, time.UTC)
year, month, day, hour, min, sec := diff(birthday, time.Now())

fmt.Printf("You are %d years, %d months, %d days, %d hours, %d mins and %d seconds old.",
    year, month, day, hour, min, sec)

Example output:

You are 36 years, 3 months, 8 days, 11 hours, 57 mins and 41 seconds old.

The magic date/time at which the Go playground time starts is: 2009-11-10 23:00:00 UTC
This is the time when Go was first announced. Let's calculate how old Go is:

goAnnounced := time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC)
year, month, day, hour, min, sec := diff(goAnnounced, time.Now())
fmt.Printf("Go was announced "+
    "%d years, %d months, %d days, %d hours, %d mins and %d seconds ago.",
    year, month, day, hour, min, sec)

Output:

Go was announced 6 years, 4 months, 29 days, 16 hours, 53 mins and 31 seconds ago.

这篇关于golang时间。因为()有几个月和几年的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆