【问题标题】:Java: Convert String to TimeStampJava:将字符串转换为时间戳
【发布时间】:2013-09-25 17:48:10
【问题描述】:

我在尝试将字符串转换为时间戳时遇到问题。我有一个日期格式为yyyy-MM-dd 的数组,我想更改为yyyy-MM-dd HH:mm:ss.SSS 的格式。所以,我使用这个代码:

final String OLD_FORMAT = "yyyy-MM-dd";
final String NEW_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
String oldDateString = createdArray[k];
String newDateString;

DateFormat formatter = new SimpleDateFormat(OLD_FORMAT);
Date d = formatter.parse(oldDateString);
((SimpleDateFormat) formatter).applyPattern(NEW_FORMAT);
newDateString = formatter.format(d);
System.out.println(newDateString);

Timestamp ts = Timestamp.valueOf(newDateString);
System.out.println(ts);

我得到以下结果。

2009-10-20 00:00:00.000

2009-10-20 00:00:00.0

但是当我尝试简单地做时

String text = "2011-10-02 18:48:05.123";
ts = Timestamp.valueOf(text);
System.out.println(ts);

我得到了正确的结果:

2011-10-02 18:48:05.123

你知道我做错了什么吗? 感谢您的帮助。

【问题讨论】:

  • 没有错。在第一种情况下您期望什么?您正在从 2009-10-20 日期创建时间戳,因此未设置时间戳的时间部分。在第二种情况下,您正在从设置时间的字符串创建时间戳。
  • 只需使用两个(Simple)DateFormat实例,无需摆弄applyPattern()
  • @GyroGearless 我不知道你是什么意思?怎么可能不 ApplyPattern?
  • @Piro 错误的问题是我有 2009-10-20 00:00:00.0 而不是 2009-10-20 00:00:00.000
  • 为什么需要三个位置/零?时间戳使用它自己的格式并且该格式是正确的并且不能更改。如果您需要打印格式化的时间戳,请将其从 Timestamp 转换回 Date 并格式化。当前的答案似乎完全错过了您所需要的,因为您的问题并不明显

标签: java date datetime timestamp


【解决方案1】:

首先将您的日期字符串转换为date,然后使用以下行将其转换为timestamp

Date date=new Date();
Timestamp timestamp = new Timestamp(date.getTime());//instead of date put your converted date
Timestamp myTimeStamp= timestamp;

【讨论】:

  • 我不确定如何输入转换后的日期。我想我的问题从 ((SimpleDateFormat) formatter).applyPattern(NEW_FORMAT) 开始; ?当我使用我的日期 Date d 时,它仍然会产生错误的结果:2009-10-20 00:00:00.0
【解决方案2】:

按照以下步骤操作以获得正确的结果:

try {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
    Date parsedDate = dateFormat.parse(yourString);
    Timestamp timestamp = new java.sql.Timestamp(parsedDate.getTime());
} catch(Exception e) { //this generic but you can control another types of exception
    // look the origin of excption 
}

请注意.parse(String) 可能会抛出ParseException

【讨论】:

  • 我尝试了你的建议,但它引发了异常。我可以解决这个问题吗?
  • 此日期模式很危险:hh 将解释小时“在上午/下午 (1-12)”。您应该使用HH 来获得问题中的“一天中的小时(0-23)”。
【解决方案3】:

你可以试一次吗...

String dob="your date String";
String dobis=null;
final DateFormat df = new SimpleDateFormat("yyyy-MMM-dd");
final Calendar c = Calendar.getInstance();
try {
    if(dob!=null && !dob.isEmpty() && dob != "")
    {
    c.setTime(df.parse(dob));
    int month=c.get(Calendar.MONTH);
    month=month+1;
    dobis=c.get(Calendar.YEAR)+"-"+month+"-"+c.get(Calendar.DAY_OF_MONTH);
    }

}

【讨论】:

  • dob != "" 是多余的和错误的 - 永远不要将字符串与 ==!= 进行比较。而且您不应该那样格式化日期,这就是 (Simple)DateFormat 的用途。
【解决方案4】:

我确定解决方案是您的 oldDateString 类似于“2009-10-20”。显然,这不包含任何低于天数的时间数据。如果你用你的新格式化程序格式化这个字符串,它应该从哪里得到分钟、秒和毫秒?

所以结果是绝对正确的:2009-10-20 00:00:00.000

你需要解决这个问题,是你第一次格式化之前的原始时间戳(包括时间数据)。

【讨论】:

  • 这个问题已有 9 个月的历史,从 cmets 可以清楚地看出,实际问题与日期字符串的格式有关,而不是与实际值有关。
【解决方案5】:
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Util {
  public static Timestamp convertStringToTimestamp(String strDate) {
    try {
      DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
       // you can change format of date
      Date date = formatter.parse(strDate);
      Timestamp timeStampDate = new Timestamp(date.getTime());

      return timeStampDate;
    } catch (ParseException e) {
      System.out.println("Exception :" + e);
      return null;
    }
  }
}

【讨论】:

  • 我更喜欢这个答案,因为它显示了代码中使用的类。我一直收到错误,因为我导入了 java.sql.Date 而不是 java.util.Date
【解决方案6】:
DateFormat formatter;
formatter = new SimpleDateFormat("dd/MM/yyyy");
Date date = (Date) formatter.parse(str_date);
java.sql.Timestamp timeStampDate = new Timestamp(date.getTime());

【讨论】:

    【解决方案7】:
    DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    
    Date date = formatter.parse(dateString);
    
    Timestamp timestamp = new Timestamp(date.getTime());
    
    System.out.println(timestamp);
    

    【讨论】:

    • 格式化字符串日期时,您可能想捕获解析异常。
    【解决方案8】:

    我想提供现代答案。当这个问题在 2013 年被问到时,使用 Timestamp 类是正确的,例如将日期时间存储到数据库中。今天的课程已经过时了。现代 Java 日期和时间 API 于三年半前的 2014 年春天随 Java 8 一起推出。我建议你改用这个。

    根据您的具体情况和具体要求,Timestamp 有两种自然替代品:

    • Instant 是时间线上的一个点。对于大多数目的,我认为使用它是最安全的。 Instant 与时区无关,即使在您的客户端设备和数据库服务器运行不同时区的情况下也能正常工作。
    • LocalDateTime 是没有时区的日期和时间,例如 2011-10-02 18:48:05.123(引用问题)。

    现代 JDBC 驱动程序(JDBC 4.2 或更高版本)和其他用于数据库访问的现代工具很乐意将InstantLocalDateTime 存储到数据类型为timestamp 的数据库列中。我在此答案中使用的两个类和其他日期时间类都属于称为 java.time 或 JSR-310 的现代 API。

    将你的字符串转换为LocalDateTime 是最简单的,所以我们先来看看:

        DateTimeFormatter formatter
                = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
        String text = "2011-10-02 18:48:05.123";
        LocalDateTime dateTime = LocalDateTime.parse(text, formatter);
        System.out.println(dateTime);
    

    打印出来

    2011-10-02T18:48:05.123
    

    如果您的字符串是 yyyy-MM-dd 格式,请改为:

        String text = "2009-10-20";
        LocalDateTime dateTime = LocalDate.parse(text).atStartOfDay();
        System.out.println(dateTime);
    

    打印出来

    2009-10-20T00:00
    

    或者更好的是,从LocalDate.parse() 获取输出并将其存储到数据类型为date 的数据库列中。

    在这两种情况下,从LocalDateTime 转换为Instant 的过程是:

        Instant ts = dateTime.atZone(ZoneId.systemDefault()).toInstant();
        System.out.println(ts);
    

    我已经使用 JVM 的默认时区指定了转换,因为这是过时的类会使用的。但是,这很脆弱,因为您的程序的其他部分或在同一 JVM 中运行的其他程序可能会在我们的脚下更改时区设置。如果可以,请改为以 region/city 格式指定时区,例如:

        Instant ts = dateTime.atZone(ZoneId.of("Europe/Athens")).toInstant();
    

    【讨论】:

    • 给出的答案是根据 OP 的问题给出的。不是对与错
    • 你是完全正确的,@OjonugwaJudeOchalifu。由于问题和答案留给子孙后代,问题是我们是否通过让 2013 年的答案独立存在或通过补充显示未来良好解决方案的答案来帮助未来的读者最好。
    【解决方案9】:

    String转java.sql.Timestamp的简单方法:

    Timestamp t = new Timestamp(DateUtil.provideDateFormat().parse("2019-01-14T12:00:00.000Z").getTime());
    

    DateUtil.java:

    import java.text.SimpleDateFormat;
    import java.util.TimeZone;
    
    public interface DateUtil {
    
      String ISO_DATE_FORMAT_ZERO_OFFSET = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
      String UTC_TIMEZONE_NAME = "UTC";
    
      static SimpleDateFormat provideDateFormat() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ISO_DATE_FORMAT_ZERO_OFFSET);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(UTC_TIMEZONE_NAME));
        return simpleDateFormat;
      }
    }
    

    【讨论】:

    • 这是一个很好的解决方案。
    • @ChristophRaab 我相信您应该将类​​/接口添加到您的解决方案中。
    【解决方案10】:

    为了完整起见,这里有一个带有 lambda 和方法参考的解决方案:

    ISO 格式?

    说明: 下面的方法

    • 如果输入有效,则将Stringyyyy-MM-dd 模式转换为Timestamp
    • 如果给定了null值,则返回null
    • 如果输入无效,则抛出 DateTimeParseException

    代码

    static Timestamp convertStringToTimestamp(String strDate) {
        return Optional.ofNullable(strDate) // wrap the String into an Optional
                       .map(str -> LocalDate.parse(str).atStartOfDay()) // convert into a LocalDate and fix the hour:minute:sec to 00:00:00
                       .map(Timestamp::valueOf) // convert to Timestamp
                       .orElse(null); // if no value is present, return null
    }
    


    验证: 可以使用这些单元测试来测试此方法: (与 Junit5Hamcrest

    @Test
    void convertStringToTimestamp_shouldReturnTimestamp_whenValidInput() {
        // given
        String strDate = "2020-01-30";
    
        // when
        final Timestamp result = convertStringToTimestamp(strDate);
    
        // then
        final LocalDateTime dateTime = LocalDateTime.ofInstant(result.toInstant(), ZoneId.systemDefault());
        assertThat(dateTime.getYear(), is(2020));
        assertThat(dateTime.getMonthValue(), is(1));
        assertThat(dateTime.getDayOfMonth(), is(30));
    }
    
    @Test
    void convertStringToTimestamp_shouldReturnTimestamp_whenInvalidInput() {
        // given
        String strDate = "7770-91-30";
    
        // when, then
        assertThrows(DateTimeParseException.class, () -> convertStringToTimestamp(strDate));
    }
    
    @Test
    void convertStringToTimestamp_shouldReturnTimestamp_whenNullInput() {
        // when
        final Timestamp result = convertStringToTimestamp(null);
    
        // then
        assertThat(result, is(nullValue()));
    }
    


    其他格式?

    通常,要解析的字符串带有另一种格式。处理它的一种方法是使用格式化程序将其转换为另一种格式。这是一个例子:

    输入:20200130 11:30

    模式:yyyyMMdd HH:mm

    输出:此输入的时间戳

    代码

    static Timestamp convertStringToTimestamp(String strDate) {
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm");
        return Optional.ofNullable(strDate) //
                       .map(str -> LocalDateTime.parse(str, formatter))
                       .map(Timestamp::valueOf) //
                       .orElse(null);
    }
    

    测试

    @Test
    void convertStringToTimestamp_shouldReturnTimestamp_whenValidInput() {
        // given
        String strDate = "20200130 11:30";
    
        // when
        final Timestamp result = convertStringToTimestamp(strDate);
    
        // then
        final LocalDateTime dateTime = LocalDateTime.ofInstant(result.toInstant(), ZoneId.systemDefault());
        assertThat(dateTime.getYear(), is(2020));
        assertThat(dateTime.getMonthValue(), is(1));
        assertThat(dateTime.getDayOfMonth(), is(30));
        assertThat(dateTime.getHour(), is(11));
        assertThat(dateTime.getMinute(), is(30));
    }
    

    【讨论】:

      【解决方案11】:

      这就是我所做的:

      Timestamp timestamp = Timestamp.valueOf(stringValue);
      

      其中stringValue 可以是任何格式的日期/时间。

      【讨论】:

      • 不,Timestamp.valueOf() 不接受任何日期和时间格式。例如不是问题中的旧格式yyyy-MM-dd。而且我仍然相信没有人应该再使用Timestamp 类了。它的设计很糟糕,是对已经设计很糟糕的Date 类的真正破解。它曾经用于在 SQL 数据库之间传输值,但现在建议改用 OffsetDateTimeLocalDateTimeInstant
      猜你喜欢
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-30
      相关资源
      最近更新 更多