【问题标题】:subtracting two java.sql.timestamp give incorrect year减去两个 java.sql.timestamp 给出不正确的年份
【发布时间】:2014-08-12 09:15:31
【问题描述】:

我正在尝试从 sql 中获取时间戳,需要计算两个时间戳之间的差异。

//startDate = 2014-07-10 16:07:00.0
//endDate = 2014-07-11 04:07:00.0
//END_DATE = 2014-07-18 08:07:00.0

private Timestamp calculateWflTime(String vehicleNum, Timestamp startDate,
        Timestamp endDate) {
    Timestamp t1 = new Timestamp (END_DATE.getTime()); //2014-07-18 08:07:00.0
    Timestamp t2 = new Timestamp (startDate.getTime()); //2014-07-10 16:07:00.0
        Timestamp wflTime = null;
        long diff=0;
        if(VEH_NUM == vehicleNum){
            diff = t1.getTime()-t2.getTime();//diff(END_DATE,startDate);
        }
    wflTime = new Timestamp( Math.abs(diff/(1000*60*60*24)));
    return wflTime; //1970-01-01 05:30:00.007
}

【问题讨论】:

  • 返回 wflTime 是 1970-01-01 05:30:00.007 ,为什么是 1970 ?
  • 默认时间。我没有得到你的代码。但这是 sql 的默认日期时间

标签: java sql date timestamp


【解决方案1】:

表达式

new Timestamp( Math.abs(diff/(1000*60*60*24)));

从领域的角度来看,在语义上是错误的。为什么?您尝试将时间量(实际上是以毫秒为单位的持续时间未锚定在时间线上)转换为此处固定为从 UNIX 纪元(1970-01-01)开始计数的时间点。这就像用几何术语将长度转换为点。

两个时间戳之间的差异不应该是一个新的时间戳,而应该只是一个持续时间(这里是您的差异变量,以毫秒为单位)。如何将其标准化为年和月取决于您。

OP 回答后更新

清洁 Joda 解决方案:

public static void main(String... args) {
    Timestamp t1 = new Timestamp(0);
    Timestamp t2 = new Timestamp(86400000 + 7261000);
    System.out.println(getDurationJoda(t1, t2));
    // output: 1 day, 2 hours, 1 minute, 1 second.
}

public static String getDurationJoda(Timestamp start, Timestamp end) {
    LocalDateTime ldtStart = new LocalDateTime(start);
    LocalDateTime ldtEnd = new LocalDateTime(end);

    Period p = new Period(ldtStart, ldtEnd, PeriodType.dayTime());

    PeriodFormatter fmt =
        new PeriodFormatterBuilder()
        .appendDays().appendSuffix(" day, ", " days, ")
        .appendHours().appendSuffix(" hour, ", " hours, ")
        .appendMinutes().appendSuffix(" minute, ", " minutes, ")
        .appendSeconds().appendSuffix(" second.", " seconds.").toFormatter();
    return fmt.print(p);
}

Time4J-解决方案

此外,您还可以使用我的库 Time4J 进行此替代,其中包含一个可本地化的 PrettyTime-class,用于从版本 1.2 开始的持续时间格式:

private static final IsoUnit DAYS = CalendarUnit.DAYS;
private static final IsoUnit HOURS = ClockUnit.HOURS;
private static final IsoUnit MINUTES = ClockUnit.MINUTES;
private static final IsoUnit SECONDS = ClockUnit.SECONDS;

public static void main(String... args) {
  Timestamp t1 = new Timestamp(0);
  Timestamp t2 = new Timestamp(86400000 + 7261000);
  System.out.println(getDurationTime4J(t1, t2));
  // output: 1 day, 2 hours, 1 minute, and 1 second
}

public static String getDurationTime4J(Timestamp start, Timestamp end) {
  PlainTimestamp startTS = TemporalTypes.SQL_TIMESTAMP.transform(start);
  PlainTimestamp endTS = TemporalTypes.SQL_TIMESTAMP.transform(end);

  Duration<?> duration = 
    Duration.in(DAYS, HOURS, MINUTES, SECONDS).between(startTS, endTS);
  return PrettyTime.of(Locale.ENGLISH).print(duration, TextWidth.WIDE);
}

最后但同样重要的是,在格式化持续时间之前尝试评估您的字符串条件并使用 equals() 而不是 ==,例如:

if (VEH_NUM.equals(vehicleNum)) {
 // call getDuration(..., ...)
} else {
 // return zero duration string
}

【讨论】:

【解决方案2】:

Unix 时间戳是用于描述时间瞬间的系统,定义为自 1970 年 1 月 1 日以来经过的秒数。

因此,如果将其减去并转换,它会显示自 1970 年以来经过的时间。

【讨论】:

    【解决方案3】:

    关于 1970 年的日期,通常所有日期都是一个数字,表示自 1970 年 1 月 1 日午夜以来的毫秒数,因此如果您将相似日期之间的差异显示为日期,那么您将得到 1970 年代的结果。您需要将答案视为毫秒,并将天、小时、分钟计算为时间。希望这会有所帮助。

    【讨论】:

    • 正确,但我会对“一般”提出异议。各种计算机系统已经使用了大约two dozen different epochs。至于计数,Unix 系统使用 seconds-since-epoch(给我们Y2038 problem),java.util.Date/Joda-Time 使用毫秒,Java 8 中的新 java.time 包使用纳秒。
    • 是的,我应该更具体一些。
    【解决方案4】:

    无论如何,我使用 JodaTime 库来计算两个时间戳之间的差异。谢谢大家的帮助。

    作为解决方案,修改后的代码现在是:

    private String calculateWflTime(String vehicleNum, Timestamp startDate,
            Timestamp endDate) {        
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String days = null, hours = null, minutes = null, seconds = null;
        Date d1 = null;
        Date d2 = null;
        Timestamp wflTime = null;
        if(VEH_NUM == vehicleNum){
            String dateStart = END_DATE.toString();
            String dateStop = startDate.toString();
        try {
            d1 = format.parse(dateStart);
            d2 = format.parse(dateStop);
    
            DateTime dt1 = new DateTime(d1);
            DateTime dt2 = new DateTime(d2);
    
             days = Days.daysBetween(dt1, dt2).getDays() + " days, ";
             hours = Hours.hoursBetween(dt1, dt2).getHours() % 24 + " hours, ";
             minutes = Minutes.minutesBetween(dt1, dt2).getMinutes() % 60 + " minutes, ";
             seconds = Seconds.secondsBetween(dt1, dt2).getSeconds() % 60 + " seconds.";
    
         } catch (Exception e) {
            e.printStackTrace();
         }          
        }
        return days+hours+minutes+seconds;
    }
    

    【讨论】:

    • 与 == 的字符串比较很少有好处,请参见“if(VEH_NUM == vehicleNum){”行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多