java datetime to int_java – Joda DateTime到Timestamp转换

本文深入探讨了时间戳与日期时间的关系,解释了时区如何影响我们对时间的感知。通过示例展示了同一时间戳在不同时区如何转化为不同的本地时间,并强调了时间戳作为时刻的唯一性。同时,文章还通过代码演示了时间转换过程,揭示了时间存储和显示的原理。
摘要由CSDN通过智能技术生成

这是一个普遍的误解,时间(可衡量的第四维度)在世界上是不同的。时间戳作为时刻是唯一的。然而日期影响我们如何“看到”时间,但实际上它是“时间”。

一个例子:两个人在同一时间看时钟。时间戳是一样的,对吧?

但其中一个在伦敦,看到中午12:00(GMT,时区偏移为0),另一个在贝尔格莱德,看到14:00(CET,中欧,夏令时,偏移为2)。

他们的感觉是不同的,但时刻是一样的。

你可以在this answer找到更多的细节。

更新

OK,它不是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对象(基本上包装一个长)和显示或输入为日期[时间]。

在你自己的答案,你是人为地添加一个偏移量,并创建一个“错误”的时间。

如果使用该时间戳创建另一个DateTime并将其打印出来,它将被偏移两次。

// Turn it back into a Joda DateTime with time zone.

DateTime dt = new DateTime(ts, DateTimeZone.forID("anytimezone"));

P.S。如果你有时间通过​​非常复杂的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));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值