2016-02-23 39 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