有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Joda DateTime到时间戳的转换

我试图在Joda中通过DateTimeZone更改Timestamp的值:

  DateTime dt = new DateTime(rs.getTimestamp("anytimestampcolumn"),
                             DateTimeZone.forID("anytimezone"));
  Timestamp ts = new Timestamp(dt.getMillis());
  • 对于DateTime,值为:2013-04-13T22:56:27.000+03:00

  • 对于TimeStamp,值为:2013-04-13 22:56:27.0

Timestamp的到来没有时区差异

如何获得正确的时区时间戳 例如,我想得到“2013-05-13 01:56:27.0”

提前谢谢

编辑:使用MySQL,列类型是TIMESTAMP当然,rsResultSet


共 (4) 个答案

  1. # 1 楼答案

    事实上,这不是一个重复的问题。这就是我在几次之后解决问题的方法:

       int offset = DateTimeZone.forID("anytimezone").getOffset(new DateTime());
    

    这是从所需时区获取偏移量的方法

    让我们回到我们的代码,我们从查询结果集中获取时间戳,并将其与时区一起使用来创建日期时间

       DateTime dt = new DateTime(rs.getTimestamp("anytimestampcolumn"),
                             DateTimeZone.forID("anytimezone"));
    

    现在,我们将把偏移量添加到datetime,并从中获取时间戳

        dt = dt.plusMillis(offset);
        Timestamp ts = new Timestamp(dt.getMillis());
    

    也许这不是得到它的实际方法,但它解决了我的问题。我希望它能帮助任何被困在这里的人

  2. # 2 楼答案

    时间(一个可测量的第四维度)在全世界是不同的,这是一个常见的误解。时间戳作为时间中的一个时刻是唯一的。然而,日期会影响我们“看”时间的方式,但实际上它是“一天中的时间”

    例如:两个人同时看钟。时间戳是一样的,对吗? 但其中一个在伦敦,中午12:00(格林尼治标准时间,时区偏移量为0),另一个在贝尔格莱德,下午14:00(CET,中欧,现在夏时制,偏移量为+2)

    他们的看法不同,但时间是一样的

    您可以在this answer中找到更多详细信息

    更新

    好的,它不是this question的副本,但它毫无意义,因为您混淆了术语“时间戳=时间时刻(客观)”和“日期[时间]=一天中的时间(主观)”

    让我们看一下您的原始问题代码,如下所示:

    // Get the "original" value from database.
    Timestamp momentFromDB = rs.getTimestamp("anytimestampcolumn");
    
    // Turn it into a Joda DateTime with time zone.
    DateTime dt = new DateTime(momentFromDB, DateTimeZone.forID("anytimezone"));
    
    // And then turn it back into a timestamp but "with time zone".
    Timestamp ts = new Timestamp(dt.getMillis());
    

    我还没有运行此代码,但我确信它每次都会打印true和相同的毫秒数:

    System.out.println("momentFromDB == dt : " + (momentFromDB.getTime() == dt.getTimeInMillis());
    System.out.println("momentFromDB == ts : " + (momentFromDB.getTime() == ts.getTime()));
    System.out.println("dt == ts : " + (dt.getTimeInMillis() == ts.getTime()));
    
    System.out.println("momentFromDB [ms] : " + momentFromDB.getTime());
    System.out.println("ts [ms] : " + ts.getTime());
    System.out.println("dt [ms] : " + dt.getTimeInMillis());
    

    但正如您自己所说,将它们打印为字符串将导致“不同”的时间,因为DateTime应用了时区。这就是为什么“时间”被存储和传输为Timestamp对象(基本上是包装一个long)并显示或输入为Date[Time]

    在你自己的回答中,你人为地增加了一个偏移量,并创造了一个“错误”的时间。 如果使用该时间戳创建另一个DateTime并将其打印出来,它将偏移两次

    // Turn it back into a Joda DateTime with time zone.
    DateTime dt = new DateTime(ts, DateTimeZone.forID("anytimezone"));
    

    另外,如果你有时间,通过非常复杂的Joda Time source code看看它是如何保存时间(毫秒)的,以及它是如何打印时间的

    JUnit测试作为证明

    import static org.junit.Assert.*;
    import static org.hamcrest.CoreMatchers.*;
    
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Locale;
    import java.util.TimeZone;
    
    import org.junit.Before;
    import org.junit.Test;
    
    
    public class WorldTimeTest {
        private static final int MILLIS_IN_HOUR = 1000 * 60 * 60;
        private static final String ISO_FORMAT_NO_TZ = "yyyy-MM-dd'T'HH:mm:ss.SSS";
        private static final String ISO_FORMAT_WITH_TZ = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
    
        private TimeZone londonTimeZone;
        private TimeZone newYorkTimeZone;
        private TimeZone sydneyTimeZone;
        private long nowInMillis;
        private Date now;
    
        public static SimpleDateFormat createDateFormat(String pattern, TimeZone timeZone) throws Exception {
            SimpleDateFormat result = new SimpleDateFormat(pattern);
            // Must explicitly set the time zone with "setCalendar()".
            result.setCalendar(Calendar.getInstance(timeZone));
            return result;
        }
    
        public static SimpleDateFormat createDateFormat(String pattern) throws Exception {
            return createDateFormat(pattern, TimeZone.getDefault());
        }
    
        public static SimpleDateFormat createDateFormat() throws Exception {
            return createDateFormat(ISO_FORMAT_WITH_TZ, TimeZone.getDefault());
        }
    
        public void printSystemInfo() throws Exception {
            final String[] propertyNames = {
                    "java.runtime.name", "java.runtime.version", "java.vm.name", "java.vm.version",
                    "os.name", "os.version", "os.arch",
                    "user.language", "user.country", "user.script", "user.variant",
                    "user.language.format", "user.country.format", "user.script.format",
                    "user.timezone" };
    
            System.out.println();
            System.out.println("System Information:");
            for (String name : propertyNames) {
                if (name == null || name.length() == 0) {
                    continue;
                }
                String value = System.getProperty(name);
                if (value != null && value.length() > 0) {
                    System.out.println("  " + name + " = " + value);
                }
            }
    
            final TimeZone defaultTZ = TimeZone.getDefault();
            final int defaultOffset = defaultTZ.getOffset(nowInMillis) / MILLIS_IN_HOUR;
            final int userOffset = TimeZone.getTimeZone(System
                    .getProperty("user.timezone")).getOffset(nowInMillis) / MILLIS_IN_HOUR;
            final Locale defaultLocale = Locale.getDefault();
    
            System.out.println("  default.timezone-offset (hours) = " + userOffset);
            System.out.println("  default.timezone = " + defaultTZ.getDisplayName());
            System.out.println("  default.timezone.id = " + defaultTZ.getID());
            System.out.println("  default.timezone-offset (hours) = " + defaultOffset);
            System.out.println("  default.locale = "
                    + defaultLocale.getLanguage() + "_" + defaultLocale.getCountry()
                    + " (" + defaultLocale.getDisplayLanguage()
                    + "," + defaultLocale.getDisplayCountry() + ")");
            System.out.println("  now = " + nowInMillis + " [ms] or "
                    + createDateFormat().format(now));
            System.out.println();
        }
    
        @Before
        public void setUp() throws Exception {
            // Remember this moment.
            now = new Date();
            nowInMillis = now.getTime(); // == System.currentTimeMillis();
    
            // Print out some system information.
            printSystemInfo();
    
            // "Europe/London" time zone is DST aware, we'll use fixed offset.
            londonTimeZone = TimeZone.getTimeZone("GMT");
            // The same applies to "America/New York" time zone ...
            newYorkTimeZone = TimeZone.getTimeZone("GMT-5");
            // ... and for the "Australia/Sydney" time zone.
            sydneyTimeZone = TimeZone.getTimeZone("GMT+10");
        }
    
        @Test
        public void testDateFormatting() throws Exception {
            int londonOffset = londonTimeZone.getOffset(nowInMillis) / MILLIS_IN_HOUR; // in hours
            Calendar londonCalendar = Calendar.getInstance(londonTimeZone);
            londonCalendar.setTime(now);
    
            int newYorkOffset = newYorkTimeZone.getOffset(nowInMillis) / MILLIS_IN_HOUR;
            Calendar newYorkCalendar = Calendar.getInstance(newYorkTimeZone);
            newYorkCalendar.setTime(now);
    
            int sydneyOffset = sydneyTimeZone.getOffset(nowInMillis) / MILLIS_IN_HOUR;
            Calendar sydneyCalendar = Calendar.getInstance(sydneyTimeZone);
            sydneyCalendar.setTime(now);
    
            // Check each time zone offset.
            assertThat(londonOffset, equalTo(0));
            assertThat(newYorkOffset, equalTo(-5));
            assertThat(sydneyOffset, equalTo(10));
    
            // Check that calendars are not equals (due to time zone difference).
            assertThat(londonCalendar, not(equalTo(newYorkCalendar)));
            assertThat(londonCalendar, not(equalTo(sydneyCalendar)));
    
            // Check if they all point to the same moment in time, in milliseconds.
            assertThat(londonCalendar.getTimeInMillis(), equalTo(nowInMillis));
            assertThat(newYorkCalendar.getTimeInMillis(), equalTo(nowInMillis));
            assertThat(sydneyCalendar.getTimeInMillis(), equalTo(nowInMillis));
    
            // Check if they all point to the same moment in time, as Date.
            assertThat(londonCalendar.getTime(), equalTo(now));
            assertThat(newYorkCalendar.getTime(), equalTo(now));
            assertThat(sydneyCalendar.getTime(), equalTo(now));
    
            // Check if hours are all different (skip local time because
            // this test could be executed in those exact time zones).
            assertThat(newYorkCalendar.get(Calendar.HOUR_OF_DAY),
                    not(equalTo(londonCalendar.get(Calendar.HOUR_OF_DAY))));
            assertThat(sydneyCalendar.get(Calendar.HOUR_OF_DAY),
                    not(equalTo(londonCalendar.get(Calendar.HOUR_OF_DAY))));
    
    
            // Display London time in multiple forms.
            SimpleDateFormat dfLondonNoTZ = createDateFormat(ISO_FORMAT_NO_TZ, londonTimeZone);
            SimpleDateFormat dfLondonWithTZ = createDateFormat(ISO_FORMAT_WITH_TZ, londonTimeZone);
            System.out.println("London (" + londonTimeZone.getDisplayName(false, TimeZone.SHORT)
                    + ", " + londonOffset + "):");
            System.out.println("  time (ISO format w/o TZ) = "
                    + dfLondonNoTZ.format(londonCalendar.getTime()));
            System.out.println("  time (ISO format w/ TZ)  = "
                    + dfLondonWithTZ.format(londonCalendar.getTime()));
            System.out.println("  time (default format)    = "
                    + londonCalendar.getTime() + " / " + londonCalendar.toString());
            // Using system default time zone.
            System.out.println("  time (default TZ)        = "
                    + createDateFormat(ISO_FORMAT_NO_TZ).format(londonCalendar.getTime())
                    + " / " + createDateFormat().format(londonCalendar.getTime()));
    
    
            // Display New York time in multiple forms.
            SimpleDateFormat dfNewYorkNoTZ = createDateFormat(ISO_FORMAT_NO_TZ, newYorkTimeZone);
            SimpleDateFormat dfNewYorkWithTZ = createDateFormat(ISO_FORMAT_WITH_TZ, newYorkTimeZone);
            System.out.println("New York (" + newYorkTimeZone.getDisplayName(false, TimeZone.SHORT)
                    + ", " + newYorkOffset + "):");
            System.out.println("  time (ISO format w/o TZ) = "
                    + dfNewYorkNoTZ.format(newYorkCalendar.getTime()));
            System.out.println("  time (ISO format w/ TZ)  = "
                    + dfNewYorkWithTZ.format(newYorkCalendar.getTime()));
            System.out.println("  time (default format)    = "
                    + newYorkCalendar.getTime() + " / " + newYorkCalendar.toString());
            // Using system default time zone.
            System.out.println("  time (default TZ)        = "
                    + createDateFormat(ISO_FORMAT_NO_TZ).format(newYorkCalendar.getTime())
                    + " / " + createDateFormat().format(newYorkCalendar.getTime()));
    
    
            // Display Sydney time in multiple forms.
            SimpleDateFormat dfSydneyNoTZ = createDateFormat(ISO_FORMAT_NO_TZ, sydneyTimeZone);
            SimpleDateFormat dfSydneyWithTZ = createDateFormat(ISO_FORMAT_WITH_TZ, sydneyTimeZone);
            System.out.println("Sydney (" + sydneyTimeZone.getDisplayName(false, TimeZone.SHORT)
                    + ", " + sydneyOffset + "):");
            System.out.println("  time (ISO format w/o TZ) = "
                    + dfSydneyNoTZ.format(sydneyCalendar.getTime()));
            System.out.println("  time (ISO format w/ TZ)  = "
                    + dfSydneyWithTZ.format(sydneyCalendar.getTime()));
            System.out.println("  time (default format)    = "
                    + sydneyCalendar.getTime() + " / " + sydneyCalendar.toString());
            // Using system default time zone.
            System.out.println("  time (default TZ)        = "
                    + createDateFormat(ISO_FORMAT_NO_TZ).format(sydneyCalendar.getTime())
                    + " / " + createDateFormat().format(sydneyCalendar.getTime()));
        }
    
        @Test
        public void testDateParsing() throws Exception {
            // Create date parsers that look for time zone information in a date-time string.
            final SimpleDateFormat londonFormatTZ = createDateFormat(ISO_FORMAT_WITH_TZ, londonTimeZone);
            final SimpleDateFormat newYorkFormatTZ = createDateFormat(ISO_FORMAT_WITH_TZ, newYorkTimeZone);
            final SimpleDateFormat sydneyFormatTZ = createDateFormat(ISO_FORMAT_WITH_TZ, sydneyTimeZone);
    
            // Create date parsers that ignore time zone information in a date-time string.
            final SimpleDateFormat londonFormatLocal = createDateFormat(ISO_FORMAT_NO_TZ, londonTimeZone);
            final SimpleDateFormat newYorkFormatLocal = createDateFormat(ISO_FORMAT_NO_TZ, newYorkTimeZone);
            final SimpleDateFormat sydneyFormatLocal = createDateFormat(ISO_FORMAT_NO_TZ, sydneyTimeZone);
    
            // We are looking for the moment this millenium started, the famous Y2K,
            // when at midnight everyone welcomed the New Year 2000, i.e. 2000-01-01 00:00:00.
            // Which of these is the right one?
            // a) "2000-01-01T00:00:00.000-00:00"
            // b) "2000-01-01T00:00:00.000-05:00"
            // c) "2000-01-01T00:00:00.000+10:00"
            // None of them? All of them?
            // For those who guessed it - yes, it is a trick question because we didn't specify
            // the "where" part, or what kind of time (local/global) we are looking for.
            // The first (a) is the local Y2K moment in London, which is at the same time global.
            // The second (b) is the local Y2K moment in New York, but London is already celebrating for 5 hours.
            // The third (c) is the local Y2K moment in Sydney, and they started celebrating 15 hours before New York did.
            // The point here is that each answer is correct because everyone thinks of that moment in terms of "celebration at midnight".
            // The key word here is "midnight"! That moment is actually a "time of day" moment illustrating our perception of time based on the movement of our Sun.
    
            // These are global Y2K moments, i.e. the same moment all over the world, UTC/GMT midnight.
            final String MIDNIGHT_GLOBAL = "2000-01-01T00:00:00.000-00:00";
            final Date milleniumInLondon = londonFormatTZ.parse(MIDNIGHT_GLOBAL);
            final Date milleniumInNewYork = newYorkFormatTZ.parse(MIDNIGHT_GLOBAL);
            final Date milleniumInSydney = sydneyFormatTZ.parse(MIDNIGHT_GLOBAL);
    
            // Check if they all point to the same moment in time.
            // And that parser ignores its own configured time zone and uses the information from the date-time string.
            assertThat(milleniumInNewYork, equalTo(milleniumInLondon));
            assertThat(milleniumInSydney, equalTo(milleniumInLondon));
    
    
            // These are all local Y2K moments, a.k.a. midnight at each location on Earth, with time zone information.
            final String MIDNIGHT_LONDON = "2000-01-01T00:00:00.000-00:00";
            final String MIDNIGHT_NEW_YORK = "2000-01-01T00:00:00.000-05:00";
            final String MIDNIGHT_SYDNEY = "2000-01-01T00:00:00.000+10:00";
            final Date midnightInLondonTZ = londonFormatLocal.parse(MIDNIGHT_LONDON);
            final Date midnightInNewYorkTZ = newYorkFormatLocal.parse(MIDNIGHT_NEW_YORK);
            final Date midnightInSydneyTZ = sydneyFormatLocal.parse(MIDNIGHT_SYDNEY);
    
            // Check if they all point to the same moment in time.
            assertThat(midnightInNewYorkTZ, not(equalTo(midnightInLondonTZ)));
            assertThat(midnightInSydneyTZ, not(equalTo(midnightInLondonTZ)));
    
            // Check if the time zone offset is correct.
            assertThat(midnightInLondonTZ.getTime() - midnightInNewYorkTZ.getTime(),
                    equalTo((long) newYorkTimeZone.getOffset(milleniumInLondon.getTime())));
            assertThat(midnightInLondonTZ.getTime() - midnightInSydneyTZ.getTime(),
                    equalTo((long) sydneyTimeZone.getOffset(milleniumInLondon.getTime())));
    
    
            // These are also local Y2K moments, just withouth the time zone information.
            final String MIDNIGHT_ANYWHERE = "2000-01-01T00:00:00.000";
            final Date midnightInLondon = londonFormatLocal.parse(MIDNIGHT_ANYWHERE);
            final Date midnightInNewYork = newYorkFormatLocal.parse(MIDNIGHT_ANYWHERE);
            final Date midnightInSydney = sydneyFormatLocal.parse(MIDNIGHT_ANYWHERE);
    
            // Check if these are the same as the local moments with time zone information.
            assertThat(midnightInLondon, equalTo(midnightInLondonTZ));
            assertThat(midnightInNewYork, equalTo(midnightInNewYorkTZ));
            assertThat(midnightInSydney, equalTo(midnightInSydneyTZ));
    
            // Check if they all point to the same moment in time.
            assertThat(midnightInNewYork, not(equalTo(midnightInLondon)));
            assertThat(midnightInSydney, not(equalTo(midnightInLondon)));
    
            // Check if the time zone offset is correct.
            assertThat(midnightInLondon.getTime() - midnightInNewYork.getTime(),
                    equalTo((long) newYorkTimeZone.getOffset(milleniumInLondon.getTime())));
            assertThat(midnightInLondon.getTime() - midnightInSydney.getTime(),
                    equalTo((long) sydneyTimeZone.getOffset(milleniumInLondon.getTime())));
    
    
            // Final check - if Y2K moment is in London ..
            final String Y2K_LONDON = "2000-01-01T00:00:00.000Z";
            // .. New York local time would be still 5 hours in 1999 ..
            final String Y2K_NEW_YORK = "1999-12-31T19:00:00.000-05:00";
            // .. and Sydney local time would be 10 hours in 2000.
            final String Y2K_SYDNEY = "2000-01-01T10:00:00.000+10:00";
    
            final String londonTime = londonFormatTZ.format(milleniumInLondon);
            final String newYorkTime = newYorkFormatTZ.format(milleniumInLondon);
            final String sydneyTime = sydneyFormatTZ.format(milleniumInLondon);
    
            // WHat do you think, will the test pass?
            assertThat(londonTime, equalTo(Y2K_LONDON));
            assertThat(newYorkTime, equalTo(Y2K_NEW_YORK));
            assertThat(sydneyTime, equalTo(Y2K_SYDNEY));
        }
    }
    
  3. # 3 楼答案

    //This Works just fine
    DateTime dt = new DateTime();
    Log.d("ts",String.valueOf(dt.now()));               
    dt=dt.plusYears(3);
    dt=dt.minusDays(7);
    Log.d("JODA DateTime",String.valueOf(dt));
    Timestamp ts= new Timestamp(dt.getMillis());
    Log.d("Coverted to java.sql.Timestamp",String.valueOf(ts));
    
  4. # 4 楼答案

    我用这种方法解决了这个问题

    String dateUTC = rs.getString("date"); //UTC
    DateTime date;
    DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").withZoneUTC();
    date = dateTimeFormatter.parseDateTime(dateUTC);
    

    通过这种方式,您可以忽略强制选择时区的服务器时区