在Java中将字符串转换为时间戳时添加夏令时

在Java中将字符串转换为时间戳时添加夏令时,java,timezone,timestamp,jodatime,dst,Java,Timezone,Timestamp,Jodatime,Dst,我的应用程序接收字符串格式的时间戳,我们使用SimpleDataFormat类中的parse()方法将该字符串转换为timestamp对象。我的应用程序在美国/纽约时区运行,因此我们在3月9日凌晨2:00到2:59之间面临时间戳的夏令时问题。我们通过修改默认时区属性来修复此问题,以确保所有夏令时字段都重置为零。但是,当我们在夏时制更改后(3月22日)使用java.util.Date类创建当前时间戳对象时,它显示为比实际的当前时间戳少1小时。这是因为更改了默认时区的属性 public class

我的应用程序接收字符串格式的时间戳,我们使用SimpleDataFormat类中的
parse()
方法将该字符串转换为
timestamp
对象。我的应用程序在美国/纽约时区运行,因此我们在3月9日凌晨2:00到2:59之间面临时间戳的夏令时问题。我们通过修改默认时区属性来修复此问题,以确保所有夏令时字段都重置为零。但是,当我们在夏时制更改后(3月22日)使用java.util.Date类创建当前时间戳对象时,它显示为比实际的当前时间戳少1小时。这是因为更改了默认时区的属性

public class DateTest {
    static TimeZone defaultTimeZone = TimeZone.getDefault();
    Timestamp timestamp1;

    public static void main(String[] args) throws Exception {
        DateTest dateTest = new DateTest();
        System.out.println("Current date before changing Timezone:" + new java.util.Date());
        //Adds one hour extra to the actual timestamp
        System.out.println("Converted Timestamp with Daylight:" + convertStringToTimestamp("2014030902101900"));
        System.out.println("=====================================================================");
        //Displays as the actual timestamp
        dateTest.setTimestamp1(convertStringToTimestampWithoutDaylight("2014030902101900"));
        System.out.println("Converted Timestamp with Daylight savings:" + dateTest.getTimestamp1());
        //1 hour is reduced compared to current timestamp as Daylight savings time is removed
        System.out.println("Current date after changing Timezone:" + new java.util.Date());
        System.out.println("=====================================================================");
        //Reset back to the original timezone
        TimeZone.setDefault(defaultTimeZone);
        Displays current timestamp
        System.out.println("Current date after Timezone reset:" + new java.util.Date());

        //Adds one hour again
        System.out.println("Converted Timestamp after Timezone reset:" + dateTest.getTimestamp1());
        System.out.println("=====================================================================");
    }
}
我们在项目中同时使用了当前时间戳对象和字符串到时间戳的转换。我也试过使用Joda Time,但最后我们需要Timestamp对象,当它转换为Timestamp时,夏令时被添加

   DateTime dateTime = DateTime.now();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateTime.toDate());
        System.out.println("Current Timestamp:" + new Timestamp(calendar.getTimeInMillis()));
        LocalDateTime localdateTime = LocalDateTime.parse("2014030902101100", DateTimeFormat.forPattern("yyyyMMddHHmmssSS"));
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(localdateTime.toDate());
        System.out.println("Converted Timestamp:" + new Timestamp(calendar2.getTimeInMillis()));
输出: 当前时间戳:2014-03-22 09:15:09.478


转换的时间戳:2014-03-09 03:10:11.0

您可以尝试使用SimpleDataFormat解析字符串,
DateTime dateTime = DateTime.now();
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateTime.toDate());
System.out.println("Current Timestamp:" + new Timestamp(calendar.getTimeInMillis()));
LocalDateTime localdateTime = LocalDateTime.parse("2014030902101100",
DateTimeFormat.forPattern("yyyyMMddHHmmssSS"));
System.out.println("Converted Timestamp:" + Timestamp.valueOf(localdateTime.toString("yyyy-mm-dd hh:mm:ss")));
差不多

SimpleDateFormat sd  = new SimpleDateFormat("yyyyMMddHHmmssSSz");
Date date = sd.parse("2014030902101100GMT-05:00");
对于z(时区)参数,您可以将GMT-05:00(GMT/UTC的纽约偏移量)添加到您手头的时间戳字符串中。 在此之后,您可以转换为任何您想要的

SimpleDataForamt.parse将为您提供日期(java.util.date)。 从日期到时间戳的转换是直接的

long ms = date.getTime();
Timestamp t =  new Timestamp(ms);

在LinkedIn上的并行线程中,您声明不知道时间戳对应的时区。在大多数情况下,这是不好的。但如果你确实处于这种情况,你可以自由地将它们视为你选择的任何时区的时间戳。如果你不知道你的时间戳对应的时区是否有日光节约,如果有的话,他们遵循什么规则,你最安全的选择是考虑它们属于没有日光节约的时区。我建议使用UTC。因此,在解析或格式化时间戳之前,您需要将SimpleDataFormat的时区设置为UTC:

    public static void main(String[] args) throws Exception {
    Date date = parseTimestamp("2014030902101100");
    System.out.println("Parsed date: " + formatDate(date));
    date = parseTimestamp("2014032202101100");
    System.out.println("Parsed date: " + formatDate(date));
}

private static Date parseTimestamp(String timestamp) throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date date = sdf.parse(timestamp);
    return date;
}

private static String formatDate(Date date) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS z");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    return sdf.format(date);
}
输出为:

Parsed date: 2014-03-09 02:10:11.00 UTC
Parsed date: 2014-03-22 02:10:11.00 UTC

为什么要将Joda Time与java.util.Date/Calendar混合使用?为了使用简单的JDBC代码插入时间戳,我将Joda Time转换为java.sql.timestamp。您应该记录该日期时间字符串的格式,而不是让我们猜测。您应该记录该日期时间字符串的含义;现在已经是纽约时间,还是UTC,还是什么?添加了日期-时间字符串格式转换。我将获取日期-时间字符串作为输入EDI消息的一部分,它不固定到任何时区,我需要在不做任何更改的情况下将其插入数据库。即使输入日期时间字符串是March 9,02.00-02.59 AM,它也不应该加1小时,即使根据美国时区它是错误的。(a)您是否理解java.util.date令人困惑,因为它在其
toString
方法中生成字符串时应用了JVM的默认时区,但实际上不包含时区(UTC)?(b) 也许你应该为你的
convertStringToTimestamp
方法提供源代码。我猜你工作太辛苦了。Joda Time应该能够简单地处理这个问题。但是你的文章很难理解。你能重写一下说,“我有这个,就是这个意思,我想去做这个。”。例如,您的意思可能是……一个系统给了我这样一个字符串,
2014030902101100
,格式为“yyyymmddhhmmsss”。该字符串表示UTC中的日期时间值(无时区偏移)。我想将该字符串转换为调整为美国/纽约时区的日期时间值,然后以ISO 8601格式打印,例如:
2014-03-24T00:59:42-05:00
。在美国/纽约时区,今年3月9日凌晨2点到2:59:59之间的时间戳与3月32日或2月29日的时间戳一样无效。只是没有表示。但是使用这种方法,1小时的DST被添加到实际的时间戳字符串中,输出被打印为“Sun Mar 09 03:10:11 EDT 2014”。正如您所说,2014年3月9日是时间更改的日子(添加了一个时间)。所以2变成了3。我不认为这是个问题,为什么你们认为这是个问题。但现在我注意到,对于09年3月2日凌晨2点之后的日期,您应该使用GMT-04:00或EDT,因为这是纽约的DST。您可以尝试使用这个
TimeZone.getDefault().inDaylightTime(newdate())。或者
TimeZone.getTimeZone(“美国/东部”).inDaylightTime(新日期())。这样你就可以检查它是否进入夏令时。是的,实际上我们会在EDI消息中以字符串形式获取时间戳,我们不知道它到底对应于北美的哪个部分:(.如果我们使用上述方法,在解析字符串时UTC时间将转换为EST格式,比实际时间缩短5小时。我需要在不影响夏令时的情况下将输入到DB中的相同时间戳插入,但当我创建新的日期对象时,它应返回当前日期和夏令时。我知道这两种说法很矛盾,但我的要求是这样的。请帮我解决这个问题。正如我前面提到的,在夏令时时区中,一些时间戳与今年2月29日或任何一年3月32日的时间戳一样无效。如果你想表示无效的时间戳,你必须表示并将它们存储为字符串。