forked from thinkgos/go-iecp5
/
time.go
executable file
·105 lines (91 loc) · 3.41 KB
/
time.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright 2020 thinkgos (thinkgo@aliyun.com). All rights reserved.
// Use of this source code is governed by a version 3 of the GNU General
// Public License, license that can be found in the LICENSE file.
package asdu
import (
"encoding/binary"
"time"
)
// CP56Time2a , CP24Time2a, CP16Time2a
// | Milliseconds(D7--D0) | Milliseconds = 0-59999
// | Milliseconds(D15--D8) |
// | IV(D7) RES1(D6) Minutes(D5--D0) | Minutes = 1-59, IV = invalid,0 = valid, 1 = invalid
// | SU(D7) RES2(D6-D5) Hours(D4--D0) | Hours = 0-23, SU = summer Time,0 = standard time, 1 = summer time,
// | DayOfWeek(D7--D5) DayOfMonth(D4--D0)| DayOfMonth = 1-31 DayOfWeek = 1-7
// | RES3(D7--D4) Months(D3--D0) | Months = 1-12
// | RES4(D7) Year(D6--D0) | Year = 0-99
// CP56Time2a time to CP56Time2a
func CP56Time2a(t time.Time, loc *time.Location) []byte {
if loc == nil {
loc = time.UTC
}
ts := t.In(loc)
msec := ts.Nanosecond()/int(time.Millisecond) + ts.Second()*1000
return []byte{byte(msec), byte(msec >> 8), byte(ts.Minute()), byte(ts.Hour()),
byte(ts.Weekday()<<5) | byte(ts.Day()), byte(ts.Month()), byte(ts.Year() - 2000)}
}
// ParseCP56Time2a 7个八位位组二进制时间,建议所有时标采用UTC,读7个字节,返回时间
// The year is assumed to be in the 20th century.
// See IEC 60870-5-4 § 6.8 and IEC 60870-5-101 second edition § 7.2.6.18.
func ParseCP56Time2a(bytes []byte, loc *time.Location) time.Time {
if len(bytes) < 7 || bytes[2]&0x80 == 0x80 {
return time.Time{}
}
x := int(binary.LittleEndian.Uint16(bytes))
msec := x % 1000
sec := x / 1000
min := int(bytes[2] & 0x3f)
hour := int(bytes[3] & 0x1f)
day := int(bytes[4] & 0x1f)
month := time.Month(bytes[5] & 0x0f)
year := 2000 + int(bytes[6]&0x7f)
nsec := msec * int(time.Millisecond)
if loc == nil {
loc = time.UTC
}
return time.Date(year, month, day, hour, min, sec, nsec, loc)
}
// CP24Time2a time to CP56Time2a 3个八位位组二进制时间,建议所有时标采用UTC
// See companion standard 101, subclass 7.2.6.19.
func CP24Time2a(t time.Time, loc *time.Location) []byte {
if loc == nil {
loc = time.UTC
}
ts := t.In(loc)
msec := ts.Nanosecond()/int(time.Millisecond) + ts.Second()*1000
return []byte{byte(msec), byte(msec >> 8), byte(ts.Minute())}
}
// ParseCP24Time2a 3个八位位组二进制时间,建议所有时标采用UTC,读3字节,返回一个时间
// See companion standard 101, subclass 7.2.6.19.
func ParseCP24Time2a(bytes []byte, loc *time.Location) time.Time {
if len(bytes) < 3 || bytes[2]&0x80 == 0x80 {
return time.Time{}
}
x := int(binary.LittleEndian.Uint16(bytes))
msec := x % 1000
sec := (x / 1000)
min := int(bytes[2] & 0x3f)
now := time.Now()
year, month, day := now.Date()
hour, _, _ := now.Clock()
nsec := msec * int(time.Millisecond)
if loc == nil {
loc = time.UTC
}
val := time.Date(year, month, day, hour, min, sec, nsec, loc)
////5 minute rounding - 55 minute span
//if min > currentMin+5 {
// val = val.Add(-time.Hour)
//}
return val
}
// CP16Time2a msec to CP16Time2a 2个八位位组二进制时间
// See companion standard 101, subclass 7.2.6.20.
func CP16Time2a(msec uint16) []byte {
return []byte{byte(msec), byte(msec >> 8)}
}
// ParseCP16Time2a 2个八位位组二进制时间,读2字节,返回一个值
// See companion standard 101, subclass 7.2.6.20.
func ParseCP16Time2a(b []byte) uint16 {
return binary.LittleEndian.Uint16(b)
}