Support non-zero minutes in the timestamp offset for JSON.
diff --git a/tests/bindings/lua/BUILD b/tests/bindings/lua/BUILD
index a065b1d..94d4929 100644
--- a/tests/bindings/lua/BUILD
+++ b/tests/bindings/lua/BUILD
@@ -37,6 +37,7 @@
     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 6b45350..4c3b64e 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 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 e2d5345..2529aa8 100644
--- a/tests/bindings/lua/test_upb.lua
+++ b/tests/bindings/lua/test_upb.lua
@@ -714,6 +714,11 @@
   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 760f96b..97019ce 100644
--- a/upb/json_decode.c
+++ b/upb/json_decode.c
@@ -1059,7 +1059,8 @@
 
   {
     /* [+-]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 @@
         /* 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;