From f7ed1f27a3f5d09f9c5e575ebe5230d92a584642 Mon Sep 17 00:00:00 2001
From: Joshua Haberman <jhaberman@gmail.com>
Date: Mon, 1 Feb 2021 18:10:09 -0800
Subject: [PATCH] Support non-zero minutes in the timestamp offset for JSON.

---
 tests/bindings/lua/BUILD        |  1 +
 tests/bindings/lua/test.proto   |  6 ++++++
 tests/bindings/lua/test_upb.lua |  5 +++++
 upb/json_decode.c               | 10 ++++++----
 4 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/tests/bindings/lua/BUILD b/tests/bindings/lua/BUILD
index a065b1df55..94d4929649 100644
--- a/tests/bindings/lua/BUILD
+++ b/tests/bindings/lua/BUILD
@@ -37,6 +37,7 @@ proto_library(
     name = "test_proto",
     testonly = 1,
     srcs = ["test.proto"],
+    deps = ["@com_google_protobuf//:timestamp_proto"],
 )
 
 lua_proto_library(
diff --git a/tests/bindings/lua/test.proto b/tests/bindings/lua/test.proto
index 6b45350208..4c3b64edb5 100644
--- a/tests/bindings/lua/test.proto
+++ b/tests/bindings/lua/test.proto
@@ -1,6 +1,8 @@
 
 syntax = "proto2";
 
+import "google/protobuf/timestamp.proto";
+
 package upb_test;
 
 message MapTest {
@@ -26,3 +28,7 @@ message UnpackedTest {
 message TestLargeFieldNumber {
   optional int32 i32 = 456214797;
 }
+
+message TestTimestamp {
+  optional google.protobuf.Timestamp ts = 1;
+}
diff --git a/tests/bindings/lua/test_upb.lua b/tests/bindings/lua/test_upb.lua
index e2d53450ba..2529aa8fc1 100644
--- a/tests/bindings/lua/test_upb.lua
+++ b/tests/bindings/lua/test_upb.lua
@@ -714,6 +714,11 @@ function test_large_field_number()
   assert_equal(msg.i32, msg2.i32)
 end
 
+function test_timestamp_minutes()
+  local msg = upb.json_decode(upb_test.TestTimestamp, '{"ts": "2000-01-01T00:00:00-06:59"}')
+  assert_equal(msg.ts.seconds, 946684800 + ((6 * 60) + 59) * 60)
+end
+
 function test_gc()
   local top = test_messages_proto3.TestAllTypesProto3()
   local n = 100
diff --git a/upb/json_decode.c b/upb/json_decode.c
index 760f96b671..97019ce6a4 100644
--- a/upb/json_decode.c
+++ b/upb/json_decode.c
@@ -1059,7 +1059,8 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
 
   {
     /* [+-]08:00 or Z */
-    int ofs = 0;
+    int ofs_hour = 0;
+    int ofs_min = 0;
     bool neg = false;
 
     if (ptr == end) goto malformed;
@@ -1070,9 +1071,10 @@ static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
         /* fallthrough */
       case '+':
         if ((end - ptr) != 5) goto malformed;
-        ofs = jsondec_tsdigits(d, &ptr, 2, ":00");
-        ofs *= 60 * 60;
-        seconds.int64_val += (neg ? ofs : -ofs);
+        ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":");
+        ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL);
+        ofs_min = ((ofs_hour * 60) + ofs_min) * 60;
+        seconds.int64_val += (neg ? ofs_min : -ofs_min);
         break;
       case 'Z':
         if (ptr != end) goto malformed;