Java:将字符串转换为时间戳


75

我在尝试将字符串转换为时间戳时遇到问题。我有一个日期格式为的数组,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()
陀螺无齿轮变速器2013年

@GyroGearless我不确定你是什么意思?怎么可能不使用ApplyPattern?
Dimitra Micha 2013年

@Piro错误的问题是我有2009-10-20 00:00:00.0而不是2009-10-20 00:00:00.000
Dimitra Micha

为什么需要三个位/零?时间戳使用其自己的格式,并且该格式正确,无法更改。如果您需要打印格式化的时间戳,请将其从“时间戳”转换回“日期”并进行格式化。当前的答案似乎完全错过了您需要的答案,因为您的问题并不明显
Piro说,Reinstate Monica

Answers:


119

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

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


我尝试了您的建议,但抛出异常。我可以解决这个问题吗?
Dimitra Micha 2013年

2
此日期格式很危险:hh将小时解释为“上午/下午(1-12)”。如问题中所述,您应该使用HH“一天中的小时(0-23)”。
Scolytus

21
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;
    }
  }
}

3
我更喜欢这个答案,因为它显示了代码中使用的类。我不断收到错误消息,因为我导入了java.sql.Date而不是java.util.Date
tartaruga_casco_mole

13

我想贡献现代的答案。当在2013年提出此问题时,使用Timestamp该类是正确的,例如用于将日期时间存储到数据库中。今天,这堂课早已过时了。现代Java日期和时间API于三年半前的2014年春季随Java 8一起发布。我建议您改用它。

根据您的具体情况,有两种自然的替代方法Timestamp

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

现代的JDBC驱动程序(JDBC 4.2或更高版本)和其他用于数据库访问的现代工具很乐意将anInstant或a存储LocalDateTime到数据类型的数据库列中timestamp。我在此答案中使用的这两个类和其他日期时间类均属于称为java.timeJSR-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()并将其存储到datatype的数据库列中date

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

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

我已使用JVM的默认时区指定了转换,因为这是过时的类将使用的转换。但是,这很脆弱,因为时区设置可能会被程序的其他部分或在同一JVM中运行的其他程序所影响。如果可以,请改以地区/城市格式指定时区,例如:

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

给出的答案是根据OP的问题给出的。没对是错
Ojonugwa Jude Ochalifu

2
您是完全正确的,@ OjonugwaJudeOchalifu。由于问题和答案留给后代使用,因此问题是我们是通过让2013年的答案独立存在还是通过补充说明未来的好的解决方案来帮助未来的读者获得最大的收益。
Ole VV

3
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

Date date = formatter.parse(dateString);

Timestamp timestamp = new Timestamp(date.getTime());

System.out.println(timestamp);

格式化字符串日期时,您可能想捕获解析异常。
eyoeldefare

3

将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;
  }
}

DateUtil从哪个库开始?
Christoph Raab

这是一个很好的解决方案。
vinicius gati


1

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

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

2
我不确定如何转换日期。我想我的问题始于((SimpleDateFormat) formatter).applyPattern(NEW_FORMAT); ?当我使用日期d时,它仍然会产生错误的结果:2009-10-20 00:00:00.0
Dimitra Micha 2013年

1

仅出于完整性考虑,以下是lambda和方法参考的解决方案:

ISO格式?

说明:以下方法

  • String带有模式的yyyy-MM-dda转换为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));
}

0

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

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

解决此问题所需的是第一次格式化之前的原始时间戳(包括时间数据)。


1
这个问题已经存在了9个月,从注释中可以明显看出,实际问题与日期字符串的格式有关,而与实际值无关。
Robby Cornelissen 2014年

0

你可以尝试一次吗...

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);
    }

}

8
dob != ""是superfluos并且是错误的-切勿将Strings与==or进行比较!=。而且,您不应该以这种方式格式化日期,即(Simple)DateFormat的用途。
陀螺仪无齿轮2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.