2016-02-23 41 views
-2

由于我已经开始投票,我决定给我的问题一些更多的细节。我的时间戳在哪里变得“搞砸了”?

我的问题是,我想存储。时间只有为了便于比较。对我来说是有意义的把它定义如下:

00:00:00 = (long) 0L 
24:00:00 = (long) 24*60*60*1000L 

PostgreSQL的documentation说,大约TIME WITHOUT TIME ZONE这样的:

time [ (p) ] [ without time zone ] 
    8 bytes | time of day (no date) | 00:00:00 - 24:00:00 | 1 microsecond/14 digits 

但由于某些原因,沿着从我的数据库的方式某处我的web应用程序时间戳正在变得混乱。

在下面,我想告诉你,我存储TIME WITHOUT TIME ZONE,从LocalTime(jodatime)映射到我的数据库,然后取回它。

抓取它从数据库返回并映射回成LocalTime对象会给我像23 Feb 2016 08:00:00 GMT这是 1456214400000,这是> 24*60*60*1000

有3到4个选项:

  1. PostgreSQL的店其实整个TIMESTAMP并显示HH:mm:ss只是为了演示
  2. jodatime的是,是不是有此发明创造。
  3. (非常不可能)我使用的映射器比我告诉他的要多。但这是不可能的,因为映射器不会触摸任何东西而不是
  4. (可能是真的)我自己搞砸了。

更多细节:

我决定添加一些更多的细节。我创建一个记录我的表shop_times

private Long createShopTimes(Long shopId, DateTime dayFrom, DateTime dayTo, LocalTime timeFrom, LocalTime timeTo, DayOfWeek dayOfWeek, ShopTimesType shopTimesType) { 

    Long timePeriodId = this.ctx.insertInto(SHOP_TIMES) 
      .set(SHOP_TIMES.SHOP_ID, shopId) 
      .set(SHOP_TIMES.DAY_OF_WEEK_ID, dayOfWeek) 
      .set(SHOP_TIMES.SHOP_TIMES_TYPE_ID, shopTimesType) 
      .set(SHOP_TIMES.DAY_FROM, dayFrom) 
      .set(SHOP_TIMES.DAY_TO, dayTo) 
      .set(SHOP_TIMES.TIME_FROM, timeFrom) 
      .set(SHOP_TIMES.TIME_TO, timeTo) 
      .returning(SHOP_TIMES.ID) 
      .fetchOne().getValue(SHOP_TIMES.ID); 

    List<ShopTimesRecord> fetchInto = this.ctx.select(
      SHOP_TIMES.TIME_FROM, 
      SHOP_TIMES.TIME_TO 
      ) 
      .from(SHOP_TIMES) 
      .fetchInto(ShopTimesRecord.class); 

    for (ShopTimesRecord shopTimesRecord : fetchInto) { 

     if(shopTimesRecord.getTimeFrom().toDateTimeToday().getMillis() > 24*60*60*1000L) { 
      System.err.println("This should not happen.."); 
     } 

     Date from = new Date(shopTimesRecord.getTimeFrom().toDateTimeToday().getMillis()); 
     Date to = new Date(shopTimesRecord.getTimeTo().toDateTimeToday().getMillis()); 

     System.out.println(from.toGMTString()); 
     System.out.println(shopTimesRecord.getTimeFrom().toDateTimeToday().getMillis()); 

     System.out.println(to.toGMTString()); 
     System.out.println(shopTimesRecord.getTimeTo().toDateTimeToday().getMillis()); 
    } 

    return timePeriodId; 
} 

正如你所看到的,我得到的东西,我不会在这一点期待:

This should not happen.. 
23 Feb 2016 08:00:00 GMT 
1456214400000 
23 Feb 2016 20:00:00 GMT 
1456257600000 

这是表shop_times那我用来存储计时信息:

CREATE TABLE shop_times (

    -- PRIMARY KEY 

    id BIGSERIAL PRIMARY KEY, 

    -- FOREIGN KEYS 

    shop_id BIGINT NOT NULL, 

    CONSTRAINT fk__shop_times__shop 
     FOREIGN KEY (shop_id) 
     REFERENCES shop(id), 

    shop_times_type_id BIGINT NOT NULL, 

    CONSTRAINT fk_shop_times__shop_times_type 
     FOREIGN KEY (shop_times_type_id) 
     REFERENCES shop_times_type(id), 

    day_of_week_id BIGINT NOT NULL, 

    CONSTRAINT fk__shop_times__day_of_week 
     FOREIGN KEY (day_of_week_id) 
     REFERENCES day_of_week(id), 

    -- ATTRIBUTES 

    day_from TIMESTAMP WITH TIME ZONE NOT NULL, 
    day_to TIMESTAMP WITH TIME ZONE NOT NULL, 

    time_from TIME WITHOUT TIME ZONE NOT NULL, 
    time_to TIME WITHOUT TIME ZONE NOT NULL, 

    -- CONSTRAINTS 

    CHECK(day_from < day_to), 

    CHECK(time_from < time_to) 

); 

我使用的映射器。但是,正如你所看到的,它只是花时间获得并进一步传递;

public class TimeWithoutTzToJodaLocalTimeConverter implements Converter<Time, LocalTime> { 
    private static final long serialVersionUID = -2736422625956918206L; 

    @Override 
    public LocalTime from(Time timestamp) { 
     LocalTime dateTime = new LocalTime(timestamp.getTime()); 
     return dateTime; 
    } 

    @Override 
    public Time to(LocalTime localTime) { 
     Time time = new Time(localTime.toDateTimeToday().getMillis()); 
     return time; 
    } 

    @Override 
    public Class<Time> fromType() { 
     return Time.class; 
    } 

    @Override 
    public Class<LocalTime> toType() { 
     return LocalTime.class; 
    } 

} 
+1

我相信,在Java中'Calendar'对象还允许将分配给它的任何时间任意数量。也许这有一个共同的原因。 –

+0

你的'CHECK'可能不会做你认为它正在做的事情......'TO_TIMESTAMP(24 * 60 * 60 * 1000)'是''1972-09-27 10:00:00''。 –

+0

@NickBarnes好的,好点。但是这并不能解决问题,因为它似乎仍然接受“2016-09-27 10:00:00”。至少这就是我得到它的结果。 – displayname

回答

1

对不起 - 不相信你。

=> SELECT '24:00:00'::time without time zone; 
    time 
---------- 
24:00:00 
(1 row) 

=> SELECT '24:00:01'::time without time zone; 
ERROR: date/time field value out of range: "24:00:01" 
LINE 1: SELECT '24:00:01'::time without time zone; 
+0

我更新了我的问题。我很可能在某个地方犯了一个错误,但实际上我看不到。请检查一下。 – displayname

+0

看看其他答案/评论以及您的扩展问题,它似乎是您的Java堆栈中的某些内容(不是Java用户,因此无法在其中进行评论)。能够检查不同图层总是有用的,但幸运的是,使用SQL RDBMS这非常简单。 –

+0

感谢您的帮助,但实际上我使用'toDateTimeToday()'我不应该使用它:/ – displayname