Java中将时间戳字符串转换为长整型

10
我需要从数据库中获取时间戳,并且只检索时间并比较两个时间。
//以下是字符串值
 String st1 = "2015-07-24T09:39:14.000Z";      
 String st2 = "2015-07-24T09:45:44.000Z";

//只检索时间09:39:14

 String s = st1.substring(st1.indexOf("T") + 1, st1.indexOf(".0"));

//字符串转长整型。

 Long time = Long.parseLong(s);

 Long tim1=Long.valueOf(s).longValue();

错误:

java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Long.parseLong(Unknown Source)
    at java.lang.Long.parseLong(Unknown Source)

2
所以你想做的是 'Long.toString("09:39:14")'。这不起作用,因为它不是一个数字。你期望的长整型数值是什么?是自1970年1月1日00:00:00 GMT以来的毫秒数吗? - logee
嗨@user2341963,我期望得到这个:09:39:14。这样我就可以比较两个时间了。 - Spartan
1
@thanga 顺便说一下,如果你从数据库中获取日期时间值,你应该得到日期时间对象,可能是java.sql.Timestamp,而不是字符串。 - Basil Bourque
6个回答

17

试试这种方法,示例代码:

java.sql.Timestamp ts2 = java.sql.Timestamp.valueOf("2015-07-24T09:45:44.000Z");
long tsTime2 = ts2.getTime();

你确定吗?文档中指出字符串必须采用JDBC格式(SQL格式),这意味着日期部分和时间部分之间需要有一个空格。中间的TISO 8601格式。 - Basil Bourque
@BasilBourque 是的,“T”会导致IllegalArgumentException异常。然后“Z”会导致NumberFormatException异常。 - pacoverflow

3
最简单的解决方案是使用Java 8的日期/时间API。
LocalDateTime from = LocalDateTime.parse("2015-07-24T09:39:14.000Z", DateTimeFormatter.ISO_DATE_TIME);
LocalDateTime to = LocalDateTime.parse("2015-07-24T09:45:44.000Z", DateTimeFormatter.ISO_DATE_TIME);
System.out.println(from + " - " + to);

LocalTime fromTime = from.toLocalTime();
LocalTime toTime = to.toLocalTime();

System.out.println(fromTime + " - " + toTime);

System.out.println(fromTime + " before " + toTime + " = " + fromTime.isBefore(toTime));
System.out.println(fromTime + " after " + toTime + " = " + fromTime.isAfter(toTime));
System.out.println(fromTime + " equals " + toTime + " = " + fromTime.equals(toTime));
System.out.println(fromTime + " compareTo " + toTime + " = " + fromTime.compareTo(toTime));

哪个输出

2015-07-24T09:39:14 - 2015-07-24T09:45:44
09:39:14 - 09:45:44
09:39:14 before 09:45:44 = true
09:39:14 after 09:45:44 = false
09:39:14 equals 09:45:44 = false
09:39:14 compareTo 09:45:44 = -1

如果您没有使用Java 8,则可以使用Joda-Time,它的工作方式类似。

Joda-Time示例...

import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.joda.time.format.ISODateTimeFormat;

public class JodaTimeTest {

    public static void main(String[] args) {
        LocalDateTime from = LocalDateTime.parse("2015-07-24T09:39:14.000Z", ISODateTimeFormat.dateTime());
        LocalDateTime to = LocalDateTime.parse("2015-07-24T09:45:44.000Z", ISODateTimeFormat.dateTime());

        LocalTime fromTime = from.toLocalTime();
        LocalTime toTime = to.toLocalTime();

        System.out.println(fromTime + " - " + toTime);

        System.out.println(fromTime + " before " + toTime + " = " + fromTime.isBefore(toTime));
        System.out.println(fromTime + " after " + toTime + " = " + fromTime.isAfter(toTime));
        System.out.println(fromTime + " equals " + toTime + " = " + fromTime.equals(toTime));
        System.out.println(fromTime + " compareTo " + toTime + " = " + fromTime.compareTo(toTime));
    }

}

输出

09:39:14.000 - 09:45:44.000
09:39:14.000 before 09:45:44.000 = true
09:39:14.000 after 09:45:44.000 = false
09:39:14.000 equals 09:45:44.000 = false
09:39:14.000 compareTo 09:45:44.000 = -1

嗨@MadProgrammer,DateTimeFormatter.ISO_DATE_TIME);这里出现了错误..已导入joda-time。谢谢 - Spartan
1
@thanga 已添加 Joda-Time 示例 - MadProgrammer
@thanga 很高兴能够帮到你。 - MadProgrammer
OP想要将时间戳转换为长整型,但是你的输出中没有任何长整型。 - pacoverflow
@pacoverflow "仅检索时间并比较两个时间" - 我跳过了标题,直接进入核心问题 - 时间比较绝不能通过比较long值来完成,应该使用适当的库来进行比较。 - MadProgrammer

3

另一种选择是使用SimpleDateFormat(与JODA Time相比可能不是最佳选择)

public static void main(String[] args) throws ParseException {
        String st1 = "2015-07-24T09:39:14.000Z";
        String st2 = "2015-07-24T09:45:44.000Z";

        String time1 = st1.substring(st1.indexOf("T") + 1, st1.indexOf(".0"));
        String time2 = st2.substring(st2.indexOf("T") + 1, st2.indexOf(".0"));

        Date dateTime1 = new java.text.SimpleDateFormat("HH:mm").parse(time1);
        Date dateTime2 = new java.text.SimpleDateFormat("HH:mm").parse(time2);

        System.out.println(dateTime1.after(dateTime2));

    }

2

简而言之

myResultSet.getObject(                         // Use JDBC 4.2 or later to get *java.time* objects rather than mere strings.
    … ,                                        // Specify the column in database of type `TIMESTAMP WITH TIME ZONE`.
    Instant.class                              // Extract from database as a `Instant` object in UTC, via JDBC.
)
.atZone( ZoneId.of( "Africa/Tunis" ) )         // Adjust into a time zone other than UTC. Returns a `ZonedDateTime` object.
.toLocalDate()                                 // Extract the date-only value, without time-of-day and without time zone. Returns a `LocalDate` object.
.atStartOfDay( ZoneId.of( "Africa/Tunis" ) )   // Determine the first moment of the day (not always 00:00). Returns a `ZonedDateTime` object.

And…

Duration.between( zdtStartOfDay , zdt )        // Represent the span of time between the first moment of the day and the target moment. Each argument is a `ZonedDateTime` object here.
    .toMillis()                                // Get entire span as a count of milliseconds. Returns a `long` primitive.
  • 无需字符串。
  • 无需java.sql.Timestamp

java.time

现代方法使用java.time类替换麻烦的旧遗留类,如java.sql.TimestampDateCalendar

MadProgrammer的答案使用了java.time,但是使用了错误的类:LocalDateTime类有意缺少任何时区或偏移量的概念,但我们的输入字符串确实具有这些信息。输入字符串末尾的Z代表Zulu,表示UTC。丢弃有价值的信息(区域/偏移信息)不是一个好习惯。

Instant类表示时间线上的一个时刻,在UTC中具有纳秒(十进制小数点后九位)的分辨率。

Instant instant = Instant.parse( "2015-07-24T09:39:14.000Z" ) ;

智能对象,不是愚蠢的字符串

我需要从数据库中获取时间戳并仅检索时间,然后比较两个时间。

以下是字符串值

使用适当的对象与您的数据库交换数据,而不仅仅是字符串。

从JDBC 4.2开始,您可以通过getObjectsetObject直接交换java.time对象。

Instant instant = myResultSet( … , Instant.class ) ;

你刚刚从数据库中直接获取了一个类似于SQL标准的TIMESTAMP WITH TIME ZONE类型的列的日期时间。

为了向数据库发送数据,请使用带有占位符的PreparedStatement

myPreparedStatement.setObject( … , instant ) ;

通过JDBC从数据库检索到的Instant对象默认为UTC时区。要获取当天的时间,您必须指定用户所在地区的墙钟时间(时区)。

请以continent/region格式指定适当的时区名称,例如America/MontrealAfrica/CasablancaPacific/Auckland。不要使用3-4个字母的伪时区,如ESTIST,因为它们不是真正的时区,没有标准化,甚至不唯一!

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;

将该时区应用于获取一个ZonedDateTime对象。 InstantZonedDateTime代表相同的时刻,即时间线上的同一点。这是一个重要的概念需要理解。两个朋友在电话中交谈,一个在加拿大魁北克,另一个在法国巴黎,同时看着墙上的时钟,在同一时刻看到的却是他们所在地区使用的不同时间。

ZoneDateTime zdt = instant.atZone( z ) ;

如果你只关心时间,可以提取一个LocalTime对象。
LocalTime lt = zdt.toLocalTime(); 

生成一个标准ISO 8601格式的String

String output = lt.toString();

生成本地化格式的字符串。
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String output = lt.format( f ) ;

但是你似乎想要从一天开始以来某些东西的计数 - 你的问题不够清晰。也许你想要整秒、毫秒的计数,或者我不知道你想要什么。

我们必须获取所需/预期时区中的一天开始时间。不要假设一天始于时间00:00:00。由于夏令时(DST)等异常情况,一天可能始于另一个时间,比如01:00:00。让java.time确定一天的开始。

ZonedDateTime zdtStartOfDay = zdt.toLocalDate().atStartOfDay( z ) ;

将经过的时间计算为 Duration

Duration d = Duration.between( zdtStartOfDay , zdt ) ;

将整个时间段提取为完整秒数。

long secondsSinceStartOfDay = d.toSeconds() ;

将整个时间段提取为毫秒数。
long millisSinceStartOfDay = d.toMillis() ;

请注意数据丢失。java.time类的分辨率为纳秒,因此当调用to...方法时,如果存在更细粒度的值,则会忽略该值的更细部分。
关于java.time: java.time框架内置于Java 8及更高版本中。这些类替代了一些麻烦的旧日期/时间类,如java.util.Date、Calendar和SimpleDateFormat。
Joda-Time项目现在处于维护模式,建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范是JSR 310。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java.sql.*类。
如何获取java.time类?

ThreeTen-Extra项目通过添加附加类扩展了java.time。该项目是java.time可能未来添加内容的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter更多


1
        String date = "2015-07-24T09:39:14.000Z";
        //Now we are getting the time only from the above string.
        String time = date.substring(12, 19); 
        System.out.println("Time is: "+time);
        //Since we cannot convert symbols like":" to long we are removing them.
        String timeInLong = time.replaceAll(":", "");
        System.out.println("Time in long format : "+Long.parseLong(timeInLong));

0
你可以尝试下面的代码,我使用了joda-time库。 java.sql.Timestamp ts2 = java.sql.Timestamp.valueOf("2015-07-24T09:45:44.000Z"); long dateLong=new DateTime(ts2).toDate().getTime();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接