You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2026/08/19 18:04:25 UTC
(plc4x) 06/12: fix(plc4go/spi): number the day of week from one, as plc4j does
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 211cd034e5125a1f0ba037388c1a3dd5b634d8b6
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Aug 19 18:06:05 2026 +0200
fix(plc4go/spi): number the day of week from one, as plc4j does
GetDayOfWeek returned Go's time.Weekday, which counts Sunday as 0 and Saturday
as 6. plc4j returns LocalDateTime#getDayOfWeek#getValue, the ISO-8601 numbering
from 1 for Monday to 7 for Sunday, and every wire format carrying this field
counts from one - a zero there means "no day given" in KNX DPT 19.001 and is
simply invalid for S7, whose mspec calls it "one 4-bit value representing 1 - 7".
S7 numbers its own field differently again, Sunday first; rotating into that
belongs in the protocol layer, since one generic value cannot serve both S7 and
KNX at once.
---
plc4go/spi/values/PlcDATE_AND_LTIME.go | 19 ++++++++-
plc4go/spi/values/PlcDATE_AND_TIME.go | 19 ++++++++-
plc4go/spi/values/PlcDATE_AND_TIME_test.go | 65 ++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/plc4go/spi/values/PlcDATE_AND_LTIME.go b/plc4go/spi/values/PlcDATE_AND_LTIME.go
index 4bbb17c805..539cda1eb5 100644
--- a/plc4go/spi/values/PlcDATE_AND_LTIME.go
+++ b/plc4go/spi/values/PlcDATE_AND_LTIME.go
@@ -75,8 +75,25 @@ func (m PlcDATE_AND_LTIME) GetDay() uint8 {
return uint8(m.value.Day())
}
+// GetDayOfWeek returns the ISO-8601 day of week: 1 == Monday .. 7 == Sunday.
+//
+// This mirrors plc4j's PlcDATE_AND_TIME#getDayOfWeek, which returns
+// LocalDateTime#getDayOfWeek#getValue, i.e. the same 1..7 ISO numbering. It is
+// deliberately NOT time.Weekday (0 == Sunday .. 6 == Saturday): every wire
+// format that carries this field numbers the days from 1, so a 0 either means
+// "no day given" (KNX DPT 19.001, knxnetip.mspec dayOfWeek) or is outright
+// invalid (S7 DATE_AND_TIME, s7.mspec: "one 4-bit value representing 1 - 7").
+//
+// Note that the S7 dow field uses a DIFFERENT 1..7 numbering (1 == Sunday ..
+// 7 == Saturday). Rotating into it is a protocol level concern that this generic
+// value cannot do for KNX and S7 at the same time, and the S7 data-io serializer
+// does not do it yet.
func (m PlcDATE_AND_LTIME) GetDayOfWeek() uint8 {
- return uint8(m.value.Weekday())
+ // time.Weekday numbers Sunday 0, ISO-8601 numbers it last as 7.
+ if weekday := m.value.Weekday(); weekday != time.Sunday {
+ return uint8(weekday)
+ }
+ return 7
}
func (m PlcDATE_AND_LTIME) GetHour() uint8 {
diff --git a/plc4go/spi/values/PlcDATE_AND_TIME.go b/plc4go/spi/values/PlcDATE_AND_TIME.go
index 5a6ade44bf..0701990cf0 100644
--- a/plc4go/spi/values/PlcDATE_AND_TIME.go
+++ b/plc4go/spi/values/PlcDATE_AND_TIME.go
@@ -73,8 +73,25 @@ func (m PlcDATE_AND_TIME) GetDay() uint8 {
return uint8(m.value.Day())
}
+// GetDayOfWeek returns the ISO-8601 day of week: 1 == Monday .. 7 == Sunday.
+//
+// This mirrors plc4j's PlcDATE_AND_TIME#getDayOfWeek, which returns
+// LocalDateTime#getDayOfWeek#getValue, i.e. the same 1..7 ISO numbering. It is
+// deliberately NOT time.Weekday (0 == Sunday .. 6 == Saturday): every wire
+// format that carries this field numbers the days from 1, so a 0 either means
+// "no day given" (KNX DPT 19.001, knxnetip.mspec dayOfWeek) or is outright
+// invalid (S7 DATE_AND_TIME, s7.mspec: "one 4-bit value representing 1 - 7").
+//
+// Note that the S7 dow field uses a DIFFERENT 1..7 numbering (1 == Sunday ..
+// 7 == Saturday). Rotating into it is a protocol level concern that this generic
+// value cannot do for KNX and S7 at the same time, and the S7 data-io serializer
+// does not do it yet.
func (m PlcDATE_AND_TIME) GetDayOfWeek() uint8 {
- return uint8(m.value.Weekday())
+ // time.Weekday numbers Sunday 0, ISO-8601 numbers it last as 7.
+ if weekday := m.value.Weekday(); weekday != time.Sunday {
+ return uint8(weekday)
+ }
+ return 7
}
func (m PlcDATE_AND_TIME) GetHour() uint8 {
diff --git a/plc4go/spi/values/PlcDATE_AND_TIME_test.go b/plc4go/spi/values/PlcDATE_AND_TIME_test.go
new file mode 100644
index 0000000000..2573782db2
--- /dev/null
+++ b/plc4go/spi/values/PlcDATE_AND_TIME_test.go
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package values
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// TestPlcDATE_AND_TIME_GetDayOfWeek pins the ISO-8601 numbering (1 == Monday ..
+// 7 == Sunday) that both consumers of this getter need.
+//
+// It used to return time.Weekday, i.e. 0 == Sunday .. 6 == Saturday. That is
+// wrong for every wire format in the tree: the KNX DPT 19.001 dayOfWeek field
+// (protocols/knxnetip .. KnxDatapoint.go) reserves 0 for "no day given", and the
+// S7 DATE_AND_TIME dow nibble is documented in s7.mspec as "representing 1 - 7",
+// so a Sunday used to serialize as the invalid value 0. plc4j's
+// PlcDATE_AND_TIME#getDayOfWeek returns LocalDateTime#getDayOfWeek#getValue,
+// which is this same 1..7 numbering.
+func TestPlcDATE_AND_TIME_GetDayOfWeek(t *testing.T) {
+ // 2024-08-19 is a Monday, so the week below walks Monday to Sunday.
+ expected := []uint8{1, 2, 3, 4, 5, 6, 7}
+ weekdays := []time.Weekday{
+ time.Monday, time.Tuesday, time.Wednesday, time.Thursday,
+ time.Friday, time.Saturday, time.Sunday,
+ }
+ for i, want := range expected {
+ day := time.Date(2024, time.August, 19+i, 10, 30, 45, 0, time.UTC)
+ t.Run(weekdays[i].String(), func(t *testing.T) {
+ assert.Equal(t, weekdays[i], day.Weekday(), "fixture sanity")
+ assert.Equal(t, want, NewPlcDATE_AND_TIME(day).GetDayOfWeek())
+ assert.Equal(t, want, NewPlcDATE_AND_LTIME(day).GetDayOfWeek())
+ })
+ }
+}
+
+// TestPlcDATE_AND_TIME_GetDayOfWeekIsAlwaysInRange guards the whole domain: no
+// input may ever produce the 0 that both wire formats treat as "unset"/invalid.
+func TestPlcDATE_AND_TIME_GetDayOfWeekIsAlwaysInRange(t *testing.T) {
+ day := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
+ for i := range 400 {
+ got := NewPlcDATE_AND_TIME(day.AddDate(0, 0, i)).GetDayOfWeek()
+ assert.GreaterOrEqual(t, got, uint8(1))
+ assert.LessOrEqual(t, got, uint8(7))
+ }
+}