Skip to content

Commit 614090d

Browse files
committed
Convert PutDate/Time between MQI strings and Go time.Time (inspired by #159)
1 parent c2d4302 commit 614090d

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

ibmmq/mqi.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ directories.
2222
package ibmmq
2323

2424
/*
25-
Copyright (c) IBM Corporation 2016, 2019
25+
Copyright (c) IBM Corporation 2016, 2021
2626
2727
Licensed under the Apache License, Version 2.0 (the "License");
2828
you may not use this file except in compliance with the License.
@@ -59,9 +59,11 @@ import "C"
5959

6060
import (
6161
"encoding/binary"
62+
_ "fmt"
6263
"io"
6364
"os"
6465
"strings"
66+
"time"
6567
"unsafe"
6668
)
6769

@@ -126,7 +128,11 @@ func (e *MQReturn) Error() string {
126128

127129
var endian binary.ByteOrder // Used by structure formatters such as MQCFH
128130
const space8 = " "
129-
131+
const (
132+
mqDateTimeFormat = "20060102150405.00 MST" // Used as the way to parse a string into a time.Time type with magic values
133+
mqDateFormat = "20060102"
134+
mqTimeFormat = "150405.00"
135+
)
130136
// This function is executed once before any other code in the package
131137
func init() {
132138
if C.MQENC_NATIVE%2 == 0 {
@@ -1383,3 +1389,32 @@ func readStringFromFixedBuffer(r io.Reader, l int32) string {
13831389
binary.Read(r, endian, tmpBuf)
13841390
return strings.TrimSpace(string(tmpBuf))
13851391
}
1392+
1393+
1394+
// The date/time fields are being taken from a valid MQMD but they still might not be
1395+
// "real" timestamps if the putting application has overridden context setting. If the values
1396+
// are invalid, then we return an empty Go value
1397+
func createGoDateTime(d string,t string) time.Time {
1398+
1399+
if len(d) == int(MQ_PUT_DATE_LENGTH) && len(t) == int(MQ_PUT_TIME_LENGTH) {
1400+
// Combine the MQI strings into a single parseable string
1401+
s := d + t[:6] + "." + t[6:] + " UTC" // MQ times are always given as UTC
1402+
goTime, err := time.Parse(mqDateTimeFormat, s)
1403+
if err != nil {
1404+
return time.Time{}
1405+
} else {
1406+
return goTime
1407+
}
1408+
} else {
1409+
return time.Time{}
1410+
}
1411+
}
1412+
1413+
// If the application has set a Go timestamp, it ought to be valid. So we can try to convert it
1414+
// to the MQ separate string formats.
1415+
func createCDateTime(goTime time.Time) (string,string) {
1416+
d:= goTime.Format(mqDateFormat) // These magic values tell Go how to parse/format between Times and strings
1417+
t:= goTime.Format(mqTimeFormat)
1418+
t = t[:6] + t[7:] // Strip the '.'
1419+
return d,t
1420+
}

ibmmq/mqiDLH.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ibmmq
22

33
/*
4-
Copyright (c) IBM Corporation 2016,2018
4+
Copyright (c) IBM Corporation 2016,2021
55
66
Licensed under the Apache License, Version 2.0 (the "License");
77
you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ import "C"
2929
import (
3030
"bytes"
3131
"encoding/binary"
32+
"time"
3233
)
3334

3435
type MQDLH struct {
@@ -40,8 +41,9 @@ type MQDLH struct {
4041
Format string
4142
PutApplType int32
4243
PutApplName string
43-
PutDate string
44-
PutTime string
44+
PutDate string // Deprecated
45+
PutTime string // Deprecated
46+
PutDateTime time.Time // Combines the PutDate and PutTime fields - takes precedence if both styles are used
4547
strucLength int // Not exported
4648
}
4749

@@ -107,6 +109,10 @@ func (dlh *MQDLH) Bytes() []byte {
107109
offset += 4
108110
copy(buf[offset:], dlh.PutApplName)
109111
offset += int(MQ_PUT_APPL_NAME_LENGTH)
112+
113+
if !dlh.PutDateTime.IsZero() {
114+
dlh.PutDate,dlh.PutTime = createCDateTime(dlh.PutDateTime)
115+
}
110116
copy(buf[offset:], dlh.PutDate)
111117
offset += int(MQ_PUT_DATE_LENGTH)
112118
copy(buf[offset:], dlh.PutTime)
@@ -144,6 +150,7 @@ func getHeaderDLH(md *MQMD, buf []byte) (*MQDLH, int, error) {
144150
dlh.PutApplName = readStringFromFixedBuffer(r, MQ_PUT_APPL_NAME_LENGTH)
145151
dlh.PutDate = readStringFromFixedBuffer(r, MQ_PUT_DATE_LENGTH)
146152
dlh.PutTime = readStringFromFixedBuffer(r, MQ_PUT_TIME_LENGTH)
153+
dlh.PutDateTime = createGoDateTime(dlh.PutDate,dlh.PutTime)
147154

148155
return dlh, dlh.strucLength, nil
149156
}

ibmmq/mqiMQMD.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ibmmq
22

33
/*
4-
Copyright (c) IBM Corporation 2016
4+
Copyright (c) IBM Corporation 2016, 2021
55
66
Licensed under the Apache License, Version 2.0 (the "License");
77
you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@ import "C"
3030

3131
import (
3232
"bytes"
33+
"time"
3334
)
3435

3536
/*
@@ -56,8 +57,9 @@ type MQMD struct {
5657
ApplIdentityData string
5758
PutApplType int32
5859
PutApplName string
59-
PutDate string
60-
PutTime string
60+
PutDate string // Deprecated
61+
PutTime string // Deprecated
62+
PutDateTime time.Time // Combines the PutDate and PutTime fields - takes precedence if both styles are used
6163
ApplOriginData string
6264
GroupId []byte
6365
MsgSeqNumber int32
@@ -119,6 +121,13 @@ func checkMD(gomd *MQMD, verb string) error {
119121
mqrc = C.MQRC_MD_ERROR // No specific error defined
120122
}
121123

124+
if len(gomd.PutDate) != 0 && len(gomd.PutDate) != C.MQ_PUT_DATE_LENGTH {
125+
mqrc = C.MQRC_MD_ERROR
126+
}
127+
if len(gomd.PutTime) != 0 && len(gomd.PutTime) != C.MQ_PUT_TIME_LENGTH {
128+
mqrc = C.MQRC_MD_ERROR
129+
}
130+
122131
if mqrc != C.MQRC_NONE {
123132
mqreturn := MQReturn{MQCC: C.MQCC_FAILED,
124133
MQRC: int32(mqrc),
@@ -162,6 +171,9 @@ func copyMDtoC(mqmd *C.MQMD, gomd *MQMD) {
162171
setMQIString((*C.char)(&mqmd.ApplIdentityData[0]), gomd.ApplIdentityData, C.MQ_APPL_IDENTITY_DATA_LENGTH)
163172
mqmd.PutApplType = C.MQLONG(gomd.PutApplType)
164173
setMQIString((*C.char)(&mqmd.PutApplName[0]), gomd.PutApplName, C.MQ_PUT_APPL_NAME_LENGTH)
174+
if !gomd.PutDateTime.IsZero() {
175+
gomd.PutDate,gomd.PutTime = createCDateTime(gomd.PutDateTime)
176+
}
165177
setMQIString((*C.char)(&mqmd.PutDate[0]), gomd.PutDate, C.MQ_PUT_DATE_LENGTH)
166178
setMQIString((*C.char)(&mqmd.PutTime[0]), gomd.PutTime, C.MQ_PUT_TIME_LENGTH)
167179
setMQIString((*C.char)(&mqmd.ApplOriginData[0]), gomd.ApplOriginData, C.MQ_APPL_ORIGIN_DATA_LENGTH)
@@ -210,6 +222,7 @@ func copyMDfromC(mqmd *C.MQMD, gomd *MQMD) {
210222
gomd.PutApplName = trimStringN((*C.char)(&mqmd.PutApplName[0]), C.MQ_PUT_APPL_NAME_LENGTH)
211223
gomd.PutDate = trimStringN((*C.char)(&mqmd.PutDate[0]), C.MQ_PUT_DATE_LENGTH)
212224
gomd.PutTime = trimStringN((*C.char)(&mqmd.PutTime[0]), C.MQ_PUT_TIME_LENGTH)
225+
gomd.PutDateTime = createGoDateTime(gomd.PutDate,gomd.PutTime)
213226
gomd.ApplOriginData = trimStringN((*C.char)(&mqmd.ApplOriginData[0]), C.MQ_APPL_ORIGIN_DATA_LENGTH)
214227

215228
for i = 0; i < C.MQ_GROUP_ID_LENGTH; i++ {

0 commit comments

Comments
 (0)