@Override
 public ZoneOffset parseZone(String zoneString) {
   return ZoneOffset.of(zoneString);
 }
 @Override
 public OffsetTime deserialize(JsonParser parser, DeserializationContext context)
     throws IOException {
   if (parser.hasToken(JsonToken.VALUE_STRING)) {
     String string = parser.getText().trim();
     if (string.length() == 0) {
       return null;
     }
     try {
       return OffsetTime.parse(string, _formatter);
     } catch (DateTimeException e) {
       _rethrowDateTimeException(parser, context, e, string);
     }
   }
   if (!parser.isExpectedStartArrayToken()) {
     if (parser.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
       return (OffsetTime) parser.getEmbeddedObject();
     }
     throw context.wrongTokenException(parser, JsonToken.START_ARRAY, "Expected array or string.");
   }
   int hour = parser.nextIntValue(-1);
   if (hour == -1) {
     JsonToken t = parser.getCurrentToken();
     if (t == JsonToken.END_ARRAY) {
       return null;
     }
     if (t != JsonToken.VALUE_NUMBER_INT) {
       _reportWrongToken(parser, context, JsonToken.VALUE_NUMBER_INT, "hours");
     }
     hour = parser.getIntValue();
   }
   int minute = parser.nextIntValue(-1);
   if (minute == -1) {
     JsonToken t = parser.getCurrentToken();
     if (t == JsonToken.END_ARRAY) {
       return null;
     }
     if (t != JsonToken.VALUE_NUMBER_INT) {
       _reportWrongToken(parser, context, JsonToken.VALUE_NUMBER_INT, "minutes");
     }
     minute = parser.getIntValue();
   }
   int partialSecond = 0;
   int second = 0;
   if (parser.nextToken() == JsonToken.VALUE_NUMBER_INT) {
     second = parser.getIntValue();
     if (parser.nextToken() == JsonToken.VALUE_NUMBER_INT) {
       partialSecond = parser.getIntValue();
       if (partialSecond < 1_000
           && !context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) {
         partialSecond *= 1_000_000; // value is milliseconds, convert it to nanoseconds
       }
       parser.nextToken();
     }
   }
   if (parser.getCurrentToken() == JsonToken.VALUE_STRING) {
     OffsetTime t =
         OffsetTime.of(hour, minute, second, partialSecond, ZoneOffset.of(parser.getText()));
     if (parser.nextToken() != JsonToken.END_ARRAY) {
       _reportWrongToken(parser, context, JsonToken.END_ARRAY, "timezone");
     }
     return t;
   }
   throw context.wrongTokenException(
       parser, JsonToken.VALUE_STRING, "Expected string for TimeZone after numeric values");
 }
public class TestPersistentOffsetTimeAsLongAndStringOffset extends DatabaseCapable {

  private static final OffsetTime[] offsetTimes =
      new OffsetTime[] {
        OffsetTime.of(LocalTime.of(12, 10, 31), ZoneOffset.UTC),
        OffsetTime.of(LocalTime.of(23, 7, 43, 120), ZoneOffset.ofHours(2))
      };

  private static EntityManagerFactory factory;

  @BeforeClass
  public static void setup() {
    factory = Persistence.createEntityManagerFactory("test1");
  }

  @AfterClass
  public static void tearDown() {
    factory.close();
  }

  @Test
  public void testPersist() {

    EntityManager manager = factory.createEntityManager();

    manager.getTransaction().begin();

    for (int i = 0; i < offsetTimes.length; i++) {

      OffsetTimeAsLongAndStringOffsetHolder item = new OffsetTimeAsLongAndStringOffsetHolder();
      item.setId(i);
      item.setName("test_" + i);
      item.setOffsetTime(offsetTimes[i]);

      manager.persist(item);
    }

    manager.flush();

    manager.getTransaction().commit();

    manager.close();

    manager = factory.createEntityManager();

    for (int i = 0; i < offsetTimes.length; i++) {

      OffsetTimeAsLongAndStringOffsetHolder item =
          manager.find(OffsetTimeAsLongAndStringOffsetHolder.class, Long.valueOf(i));

      assertNotNull(item);
      assertEquals(i, item.getId());
      assertEquals("test_" + i, item.getName());
      assertEquals(offsetTimes[i], item.getOffsetTime());
    }

    verifyDatabaseTable(
        manager, OffsetTimeAsLongAndStringOffsetHolder.class.getAnnotation(Table.class).name());

    manager.close();
  }
}