在java中将日期从一个时区转换为另一个时区

在java中将日期从一个时区转换为另一个时区,java,timezone,simpledateformat,Java,Timezone,Simpledateformat,我想使用java中的SimpleDataFormat类将日期从一个时区转换为另一个时区。但不知何故,它产生了不同的结果,这些结果被认为是在同一时区 这是一个测试用例,它生成一个结果作为IST,另一个结果作为GMT。我认为它应该只为这两种情况生成GMT public class TestOneCoreJava { public static void main(String[] args) throws ParseException {// Asia/Calcutta D

我想使用java中的SimpleDataFormat类将日期从一个时区转换为另一个时区。但不知何故,它产生了不同的结果,这些结果被认为是在同一时区

这是一个测试用例,它生成一个结果作为IST,另一个结果作为GMT。我认为它应该只为这两种情况生成GMT

public class TestOneCoreJava {

    public static void main(String[] args) throws ParseException {// Asia/Calcutta
        DateFormat formatter = new SimpleDateFormat("dd-MMM-yy hh:mm:ss a");
        System.out.println(getDateStringToShow(formatter.parse("26-Nov-10 03:31:20 PM +0530"),"Asia/Calcutta", "Europe/Dublin", false));
        System.out.println(getDateStringToShow(formatter.parse("02-Oct-10 10:00:00 AM +0530"),"Asia/Calcutta", "Europe/Dublin", false));
        //------Output--
        //26-Nov-10 GMT
        //02-Oct-10 IST
    }

    public static String getDateStringToShow(Date date,
            String sourceTimeZoneId, String targetTimeZoneId, boolean includeTime) {
        String result = null;

        // System.out.println("CHANGING TIMEZONE:1 "+UnitedLexConstants.SIMPLE_FORMAT.format(date));
        String date1 = new SimpleDateFormat("dd-MMM-yy hh:mm:ss a").format(date);

        SimpleDateFormat sourceTimeZoneFormat = new SimpleDateFormat("Z");
        sourceTimeZoneFormat.setTimeZone(TimeZone.getTimeZone(sourceTimeZoneId));

        date1 += " " + sourceTimeZoneFormat.format(date);

        // Changed from 'Z' to 'z' to show IST etc, in place of +5:30 etc.
        SimpleDateFormat targetTimeZoneFormat = new SimpleDateFormat("dd-MMM-yy hh:mm:ss a z");
        targetTimeZoneFormat.setTimeZone(TimeZone.getTimeZone(targetTimeZoneId));

        SimpleDateFormat timeZoneDayFormat = null;
        if (includeTime) {
            timeZoneDayFormat = targetTimeZoneFormat;
        } else {
            timeZoneDayFormat = new SimpleDateFormat("dd-MMM-yy z");
        }
        timeZoneDayFormat.setTimeZone(TimeZone.getTimeZone(targetTimeZoneId));
        try {
            result = timeZoneDayFormat.format(targetTimeZoneFormat.parse(date1));
            // System.out.println("CHANGING TIMEZONE:3 "+result);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }
}

在处理谷歌API中的时区问题时。我遇到过这样的问题

看看你的这段代码:-

 System.out.println(getDateStringToShow(formatter.parse("26-Nov-10 03:31:20 PM 
 +0530"),"Asia/Calcutta", "Europe/Dublin", false));
 System.out.println(getDateStringToShow(formatter.parse("02-Nov-10 10:00:00 AM 
 +0530"),"Asia/Calcutta", "Europe/Dublin", false));
如果我将以上内容作为输入,它将按照我们希望的方式运行


如果你仍然想这样做,那么你必须根据你的需要进行计算

比如用数学方法调整时间和类似的事情


或者,您的案例的简单修复将是这样的

SimpleDateFormat d =new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
d.setTimeZone(TimeZone.getTimeZone("Europe/Dublin"));
Date firsttime = d.parse("2013-12-19T03:31:20");
Date seondtime = d.parse("2013-12-19T10:00:00");

System.out.println(getDateStringToShow(firsttime,"Asia/Calcutta",
"Europe/Dublin", false));
System.out.println(getDateStringToShow(seondtime,"Asia/Calcutta", 
"Europe/Dublin", false));

我的建议将作为参考。比旧时更受欢迎。

tl;博士 使用现代java.time类,特别是和。看

2018-09-18T21:47:32.035960+01:00[非洲/突尼斯]

有关UTC,请致电

避免使用三个字母的时区代码 避免使用三个字母的时区代码。它们既不是标准化的,也不是独特的。例如,您使用的“IST”可能意味着印度标准时间、爱尔兰标准时间,或者其他

使用适当的工具。时区的定义及其名称经常更改,因此请随时更新您的来源。例如,旧的“亚洲/加尔各答”现在是“亚洲/加尔各答”。不仅仅是名字;政府因改变时区的规则/行为而臭名昭著,有时是在最后一刻

避免j.u.Date 避免使用捆绑的java.util.Date和Calendar类。它们是出了名的麻烦,在Java8中将被新的(其灵感来源于)所取代

java.time
Instant
学会在UTC而不是你自己的狭隘时区思考和工作。日志记录、数据交换和数据存储通常应在UTC中完成

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
instant.toString():2018-09-18T20:48:43.354953Z

ZoneDateTime
调整到一个时区。同一时刻,时间线上的同一点,不同的挂钟时间。应用
区域ID
(时区)以获取对象

我们可以使用
Instant
zoneDateTime
再次进行调整

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdtKolkata = zdtMontreal.withZoneSameInstant​( zKolkata ) ;
ISO 8601 对这些类中的任何一个调用
toString
,都会在标准类中生成文本。
ZonedDateTime
类通过在方括号中添加时区名称,明智地扩展了标准

当以文本形式交换日期时间值时,始终使用ISO 8601格式。不要使用问题中提到的自定义格式或本地化格式

默认情况下,java.time类使用标准格式来解析和生成字符串

Instant instant = Instant.parse( "2018-01-23T01:23:45.123456Z" ) ;
使用标准格式可以避免问题中出现的所有混乱的字符串操作

调整到UTC 通过提取
即时
,始终可以将
分区日期时间
返回UTC

Instant instant = zdtKolkata.toInstant() ;
DateTimeFormatter
若要以其他格式表示日期时间值,请初始化。你会发现许多例子和讨论


更新:Joda Time项目现在处于维护模式,并建议迁移到java.Time类。我将把这一部分作为历史保留下来

乔达时间 小心java.util.Date对象,它们看起来有时区,但实际上没有。在约达时间,a确实知道其指定的时区。通常应指定所需的时区。否则,将分配JVM的默认时区

Joda Time主要使用不可变对象。创建新的新实例而不是修改实例。在调用方法(如)时,将返回一个新的fresh DateTime实例,保持原始对象不变

//DateTime now=new DateTime();//自动指定默认时区。
//将java.util.Date转换为Joda时间。
java.util.Date Date=新建java.util.Date();
DateTime now=新的日期时间(日期);//自动指定默认时区。
DateTimeZone timeZone=DateTimeZone.forID(“亚洲/加尔各答”);
DateTime nowIndia=now.toDateTime(时区);
//对于UTC/GMT,使用内置常量。
DateTime nowUtcGmt=nowIndia.toDateTime(DateTimeZone.UTC);
//将Joda Time转换为java.util.Date。
java.util.Date date2=nowIndia.toDate();
转储到控制台

System.out.println(“日期:+date”);
System.out.println(“now:+now”);
System.out.println(“nowIndia:+nowIndia”);
System.out.println(“nowUtcGmt:+nowUtcGmt”);
System.out.println(“date2:+date2”);
当运行时

日期:2014年1月25日星期六16:52:28太平洋标准时间
现在:2014-01-25T16:52:28.003-08:00
印度时间:2014-01-26T06:22:28.003+05:30
nowUtcGmt:2014-01-26T00:52:28.003Z
日期2:2014年1月25日星期六16:52:28太平洋标准时间

关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*

从哪里获得java.time类

  • 、和更高版本-标准Java API的一部分,带有捆绑实现。
    • Java9添加了一些次要功能和修复
    • 大多数java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类
    • 对于早期的Android(
      Instant instant = Instant.parse( "2018-01-23T01:23:45.123456Z" ) ;
      
      Instant instant = zdtKolkata.toInstant() ;