Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在时区之间转换,即使相同的时区更改了日期(UTC到UTC)_Java_Datetime_Timezone_Jodatime - Fatal编程技术网

Java 在时区之间转换,即使相同的时区更改了日期(UTC到UTC)

Java 在时区之间转换,即使相同的时区更改了日期(UTC到UTC),java,datetime,timezone,jodatime,Java,Datetime,Timezone,Jodatime,我一直很困惑为什么下面的代码会导致我的日期从25号改为24号 SimpleDateFormat sd = new SimpleDateFormat("dd/MM/yyyy"); DateTimeZone customerZone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("UTC")); DateTimeZone serverZone = DateTimeZone.UTC; Date date = sd.parse("25/05/2014"

我一直很困惑为什么下面的代码会导致我的日期从25号改为24号

SimpleDateFormat sd = new SimpleDateFormat("dd/MM/yyyy");
DateTimeZone customerZone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("UTC"));
DateTimeZone serverZone = DateTimeZone.UTC;

Date date = sd.parse("25/05/2014");

DateTime source = new DateTime(date).withZone(customerZone).withHourOfDay(5);

LocalDateTime ldate = new LocalDateTime(source, serverZone);
System.out.println(ldate.toDate()); //expected to be Sat May 25 05:00:00 
结果
“2014年5月24日星期六05:00:00 SAST”

我认为南非的2014年5月25日00:00:00被视为UTC客户时区的24/5,10点。最后,小时设置为早上5点。

您没有为
SimpleDataFormat
设置时区,因此它默认为您环境的时区,我猜是
“非洲/约翰内斯堡”
,因为您的结果中有SAST

所以当你做这部分的时候:

SimpleDateFormat sd = new SimpleDateFormat("dd/MM/yyyy");
Date date = sd.parse("25/05/2014");
日期
对象将在SAST的午夜,即UTC的前一个晚上10点。剩下的就从这里开始了,因为您从那时起就在与UTC合作

另外,在最后,调用
toDate
,这将生成一个
Date
对象。输出时,本地时区也会影响结果

您可以考虑在<代码> SimpleDateFormat < /Cord>对象上调用<代码> StimeTimeStave>代码>。这至少会使开头部分正确。但是您还应该使用

format
方法输出最终字符串

然而,一个更好的解决方案是使用。这样您就不必使用
SimpleDateFormat
Date

正确。省略时区时,将应用JVM的默认时区。我建议始终指定时区,而不是依赖隐式默认值,即使是通过显式调用
getDefault()
完成

纯乔达时间 仅供参考,以下是一些示例代码,用于更好地完成此工作。这种方式只使用。正如您的问题所示,混合使用Joda Time和java.util.Date/Calendar会导致混乱和痛苦。此外,java.util.Date、.Calendar和SimpleDataFormat类是出了名的麻烦,应该避免使用

顺便说一下,不需要调用getTimeZone并传递TimeZone对象。Joda Time具有UTC的内置常量:
DateTimeZone.UTC

DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd/MM/yyyy" ); // Usually I specify a Locale as well. But in this case, no need (no names of days or months).
DateTimeZone customerTimeZone = DateTimeZone.UTC;

String input = "25/05/2014";
DateTime customerDateTime = formatter.withZone( customerTimeZone ).parseDateTime( input );

DateTime customerDateTimeAtFive = customerDateTime.withHourOfDay( 5 );  // Using customerTimeZone.
不知道为什么您通过转换为LocalDateTime故意丢失时区信息。如果目标是在服务器上处理UTC格式的日期时间值,则无需丢失时区。服务器端代码应该使用明确分配给UTC时区的DateTime对象。您可以通过以下方式调整时区:

DateTime serverDateTime = customerDateTimeAtFive.withZone( DateTimeZone.UTC );
但无论如何,如果您坚持(与问题中的代码相同)

转储到控制台

System.out.println( "customerTimeZone: " + customerTimeZone );
System.out.println( "input: " + input );
System.out.println( "customerDateTime: " + customerDateTime );
System.out.println( "customerDateTimeAtFive: " + customerDateTimeAtFive );
System.out.println( "serverDateTime: " + serverDateTime );
System.out.println( "serverTimeZone: " + serverTimeZone );
System.out.println( "localDateTime: " + localDateTime );
跑步的时候

customerTimeZone:UTC
输入:25/05/2014
客户日期:2014-05-25T00:00:00.000Z
customerDateTimeAtFive:2014-05-25T05:00:00.000Z
服务器日期时间:2014-05-25T05:00:00.000Z
服务器时区:UTC
本地日期时间:2014-05-25T05:00:00.000

罗勒的好例子。谢谢!:)谢谢你的全面回答。我应该在我的问题中包含完整的方法,以便回答您关于我为什么使用LocalDateTime的不确定性。上面的代码是返回java.util.Date的方法的一部分。因此使用LocalDateTime。之所以使用它,是因为DateTime.toDate()方法返回一个新的Java日期对象,该对象由DateTime对象的毫秒构成。但是.withTimeZone()方法不会更改毫秒数,导致返回的java.util.Date是没有应用时区的原始日期。你说得对。谢谢你的回答!
System.out.println( "customerTimeZone: " + customerTimeZone );
System.out.println( "input: " + input );
System.out.println( "customerDateTime: " + customerDateTime );
System.out.println( "customerDateTimeAtFive: " + customerDateTimeAtFive );
System.out.println( "serverDateTime: " + serverDateTime );
System.out.println( "serverTimeZone: " + serverTimeZone );
System.out.println( "localDateTime: " + localDateTime );