当前位置: 首页 > 知识库问答 >
问题:

用java实现从一个时区到另一个时区的日期转换

南门承教
2023-03-14

这里是一个测试用例,它生成的一个结果是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;
    }
}

共有1个答案

常嘉平
2023-03-14

使用现代java.time类,特别是zoneddatetimezoneid。请参阅Oracle教程。

ZonedDateTime                         // Represent a date and time-of-day in a specific time zone.
.now(                                 // Capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone). 
    ZoneId.of( "Pacific/Auckland" )   // Specify time zone using proper name in `Continent/Region` format. Never use 3-4 letter pseudo-zone such as IST or PST or EST.
)                                     // Returns a `ZonedDateTime` object.
.withZoneSameInstant(                 // Adjust from one time zone to another. Same point on the timeline, same moment, but different wall-clock time.
    ZoneId.of( "Africa/Tunis" )       
)                                     // Returns a new fresh `ZonedDateTime` object rather than altering/“mutating” the original, per immutable objects pattern.
.toString()                           // Generate text in standard ISO 8601 format, extended to append name of zone in square brackets.

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

对于UTC,调用ZonedDateTime::ToInstant

避免那些三个字母的时区代码。它们既不规范,也不独特。例如,您使用的“ist”可能意味着印度标准时间、爱尔兰标准时间,或许还有其他。

使用正确的时区名称。时区的定义和它们的名称经常更改,因此保持您的源是最新的。例如,旧的“亚洲/加尔各答”现为“亚洲/加尔各答”。而不仅仅是名字;政府因改变一个时区的规则/行为而臭名昭著,偶尔会在最后一刻改变。

避免使用绑定的java.util.Date和Calendar类。它们是出了名的麻烦,在Java8中将被新的Java.time.*包(它的灵感来自Joda-Time)所取代。

学会用UTC来思考和工作,而不是你自己的狭隘时区。日志记录、数据交换和数据存储通常应该用UTC完成。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Instant.ToString():2018-09-18T20:48:43.354953 Z

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

ZoneId zMontreal = ZoneId.of( "America/Montreal" ) ;  
ZonedDateTime zdtMontreal = instant.atZone( zMontreal ) ;  // Same moment, different wall-clock time.

我们可以使用instantzoneddatetime再次进行调整。

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdtKolkata = zdtMontreal.withZoneSameInstant​( zKolkata ) ;

对这些类中的任何一个调用ToString都会生成标准ISO 8601类中的文本。ZonedDateTime类通过在方括号中添加时区名称,明智地扩展了标准。

当将日期-时间值交换为文本时,请始终使用ISO 8601格式。不要使用自定义格式或本地化格式,如您的问题所示。

在默认情况下,java.time类使用标准格式来html" target="_blank">解析和生成字符串。

Instant instant = Instant.parse( "2018-01-23T01:23:45.123456Z" ) ;

使用标准格式可以避免问题中出现的所有混乱的字符串操作。

通过提取instant,您始终可以将zoneddatetime返回到UTC。

Instant instant = zdtKolkata.toInstant() ;

若要以其他格式表示日期时间值,请搜索DateTimeFormatter类的堆栈溢出。你会发现很多例子和讨论。

更新:Joda-Time项目现在处于维护模式,并建议迁移到java.time类。我要把这一节完好无损地留作历史。

当心java.util.Date对象,这些对象看起来像有时区,但实际上没有。在Joda-Time中,DateTime确实知道其分配的时区。通常应指定所需的时区。否则,将分配JVM的默认时区。

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

//DateTime now = new DateTime(); // Default time zone automatically assigned.

// Convert a java.util.Date to Joda-Time.
java.util.Date date = new java.util.Date();
DateTime now = new DateTime( date );  // Default time zone automatically assigned.

DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime nowIndia = now.toDateTime( timeZone );

// For UTC/GMT, use built-in constant.
DateTime nowUtcGmt = nowIndia.toDateTime( DateTimeZone.UTC );

// Convert from Joda-Time to java.util.Date.
java.util.Date date2 = nowIndia.toDate();

转储到控制台…

System.out.println( "date: " + date );
System.out.println( "now: " + now );
System.out.println( "nowIndia: " + nowIndia );
System.out.println( "nowUtcGmt: " + nowUtcGmt );
System.out.println( "date2: " + date2 );

运行时…

date: Sat Jan 25 16:52:28 PST 2014
now: 2014-01-25T16:52:28.003-08:00
nowIndia: 2014-01-26T06:22:28.003+05:30
nowUtcGmt: 2014-01-26T00:52:28.003Z
date2: Sat Jan 25 16:52:28 PST 2014

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

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

从哪里获取java.time类?

    null
    null
    null
 类似资料:
  • 我期待但我得到的是作为。我错过了什么?

  • 问题内容: 基本上,我需要的是一个脚本,该脚本在提供时间和时区时可以返回另一个时区中的时间。 我的主要问题是: 从哪里获取GMT的时间偏差-是否有公共数据库可用于此? 如何也考虑夏时制(DST)的差异。 如何将其全部包装到PHP类中?或者是否已有这样的类? 问题答案: format('Y-m-d H:i:sP') . "\n"; 上面的示例将输出: 编辑:就像Pekka所说的:DateTime类从

  • 问题内容: 我已编写此代码将当前系统日期和时间转换为其他时区。我没有收到任何错误,但没有得到预期的输出。就像我在特定时间执行程序一样。我的输出是:: 当前 印度 时间是:: :: 中部标准时间 的日期和 时间 是:: 根据 CST时区 的实际时间是:: 所以有一些 时间间隔 。而且我不知道为什么会这样。任何帮助将不胜感激..代码是:: 问题答案: 通过网络。可以用谷歌搜索。无论如何,这是一个适合您

  • 问题内容: 具体来说,给定服务器的时区(系统时间角度)和时区输入,我如何计算系统时间,就像它在那个新时区中一样(无论夏时制如何)? 问题答案: 如果知道您的原始时区和要将其转换为的新时区,那么结果将非常简单: 为当前时区和新时区都创建一个对象,例如。如果您不知道时区的官方名称,只需拨打以下电话即可找到所有官方时区的列表 呼叫使用当前时区的pytz对象与你的日期时间/时间戳输入到它定位到当前时区。例

  • 问题内容: 法国说如何将时区中的当前时间(日期时间)转换为另一个时区?我在SO中环顾四周,但没有找到任何可以帮助我的帖子。我正在使用SQL Server 2008。 问题答案: 在这里检查

  • 问题内容: 我正在寻找一种将一个时区的日期转换为另一个时区的函数。 它需要两个参数, 日期(格式为“ 2019/04/10 10:10:30 +0000”) 时区字符串(“亚洲/雅加达”) 是否有捷径可寻? 问题答案: var aestTime = new Date().toLocaleString(“en-US”, {timeZone: “Australia/Brisbane”});