jrmccluskey commented on code in PR #40154:
URL: https://github.com/apache/beam/pull/40154#discussion_r4262089834


##########
sdks/go/pkg/beam/core/runtime/graphx/schema/logicaltypes.go:
##########


Review Comment:
   Now that users will be interacting with this code more directly, it's 
probably a good idea to include a duplication check here (I am okay with this 
being a follow-up.)



##########
sdks/go/pkg/beam/core/runtime/graphx/schema/standard_logical_types.go:
##########
@@ -0,0 +1,136 @@
+// 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
+//
+//    http://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 schema
+
+import (
+       "time"
+
+       "github.com/apache/beam/sdks/v2/go/pkg/beam/core/runtime"
+       "github.com/apache/beam/sdks/v2/go/pkg/beam/core/util/reflectx"
+       "github.com/apache/beam/sdks/v2/go/pkg/beam/internal/errors"
+)
+
+// URNs of the standard logical types defined in schema.proto.
+const (
+       // URNDate identifies the Date logical type.
+       URNDate = "beam:logical_type:date:v1"
+       // URNMicrosInstant identifies the MicrosInstant logical type.
+       URNMicrosInstant = "beam:logical_type:micros_instant:v1"
+)
+
+// Date is a calendar date without a time zone or time of day, the
+// beam:logical_type:date:v1 logical type. It is stored as the number of days
+// since 1970-01-01 in an INT64 field. Time and String normalize out of range
+// fields as time.Date does. Encoding fails unless the fields form a valid
+// date with a year from -999999999 to 999999999, and decoding fails for a day
+// count outside that range.
+type Date struct {
+       Year  int
+       Month time.Month
+       Day   int
+}

Review Comment:
   Date doesn't have a valid zero value (e.g. `Date{}` won't encode and will be 
rejected.) I would suggest treating `Date{}` as the epoch for clarity.



##########
sdks/go/pkg/beam/core/runtime/graphx/schema/standard_logical_types.go:
##########
@@ -0,0 +1,136 @@
+// 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
+//
+//    http://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 schema
+
+import (
+       "time"
+
+       "github.com/apache/beam/sdks/v2/go/pkg/beam/core/runtime"
+       "github.com/apache/beam/sdks/v2/go/pkg/beam/core/util/reflectx"
+       "github.com/apache/beam/sdks/v2/go/pkg/beam/internal/errors"
+)
+
+// URNs of the standard logical types defined in schema.proto.
+const (
+       // URNDate identifies the Date logical type.
+       URNDate = "beam:logical_type:date:v1"
+       // URNMicrosInstant identifies the MicrosInstant logical type.
+       URNMicrosInstant = "beam:logical_type:micros_instant:v1"
+)
+
+// Date is a calendar date without a time zone or time of day, the
+// beam:logical_type:date:v1 logical type. It is stored as the number of days
+// since 1970-01-01 in an INT64 field. Time and String normalize out of range
+// fields as time.Date does. Encoding fails unless the fields form a valid
+// date with a year from -999999999 to 999999999, and decoding fails for a day
+// count outside that range.
+type Date struct {
+       Year  int
+       Month time.Month
+       Day   int
+}
+
+// DateOf returns the Date of t in t's location.
+func DateOf(t time.Time) Date {
+       y, m, d := t.Date()
+       return Date{Year: y, Month: m, Day: d}
+}
+
+// Time returns the start of the date in UTC.
+func (d Date) Time() time.Time {
+       return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, time.UTC)
+}
+
+// String returns the date in ISO 8601 format, such as 2006-01-02.
+func (d Date) String() string {
+       return d.Time().Format("2006-01-02")
+}
+
+const secondsPerDay = 24 * 60 * 60
+
+// minDateDays and maxDateDays bound the supported days since the epoch.
+var (
+       minDateDays = time.Date(-999999999, time.January, 1, 0, 0, 0, 0, 
time.UTC).Unix() / secondsPerDay
+       maxDateDays = time.Date(999999999, time.December, 31, 0, 0, 0, 0, 
time.UTC).Unix() / secondsPerDay
+)
+
+func dateToStorage(d Date) (int64, error) {
+       t := d.Time()
+       // Out of range fields can overflow in time.Date, so only a date that
+       // round trips is encoded.
+       if DateOf(t) != d {
+               return 0, errors.Errorf("%d-%02d-%02d is not a valid date", 
d.Year, d.Month, d.Day)
+       }
+       days := t.Unix() / secondsPerDay
+       if days < minDateDays || days > maxDateDays {
+               return 0, errors.Errorf("date %v is out of range", d)
+       }
+       return days, nil
+}
+
+func dateFromStorage(days int64) (Date, error) {
+       if days < minDateDays || days > maxDateDays {
+               return Date{}, errors.Errorf("%v days since the epoch is out of 
the supported date range", days)
+       }
+       return DateOf(time.Unix(days*secondsPerDay, 0).UTC()), nil
+}
+
+// MicrosInstant is a timestamp with microsecond precision, the
+// beam:logical_type:micros_instant:v1 logical type. It is stored as a row of
+// the seconds and the microseconds since the epoch. Encoding a value with
+// sub microsecond precision fails; truncate such values with 
time.Time.Truncate
+// first.
+type MicrosInstant time.Time

Review Comment:
   Consider implementing String() and Equals() methods on this type for ease of 
use. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to