English 中文(简体)
当地和服务器间隔时间的不同日期
原标题:Different date in local and the server java date time
The bounty expires in 24 minutes. Answers to this question are eligible for a +100 reputation bounty. Carlene12War is looking for an answer from a reputable source.

When I run below code which converts a xml date to java date, it prints different value(CST) in local vs different value(UTC) in the server running the same code, what could be reason for it? How can I always print this date in CST format which I am getting in my local. I can t use latest java date API and have to use XML based date.

    import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.Date;
import java.util.TimeZone;

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.Date;
import java.util.TimeZone;

public class Demo {
    public static final TimeZone TIMEZONE = TimeZone.getTimeZone("America/Chicago");

    public static Date convertDate(XMLGregorianCalendar value) {
        if (value == null) {
            return null;
        } else {
            if (value.getXMLSchemaType() == DatatypeConstants.DATE) {
                return value.toGregorianCalendar().getTime();
            } else {
                return value.toGregorianCalendar(TIMEZONE, null, null).getTime();
            }
        }
    }

    public static void main(String[] args) {
        try {
            // Parse the XML date string into XMLGregorianCalendar
            XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2024-02-09T01:57:33.240-06:00");
            // Convert XMLGregorianCalendar to Date
            Date date = convertDate(xmlDate);
            // Print the result
            System.out.println("Date: " + date);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

日期: Fri Feb 09 01:57:33CST 2024 - local production (Intellij - my mac time ZoneCST)

日期: Fri Feb 09 07:57:33 UTC 2024 - server输出(

I need to store the date in america/chicago timezone irrespective of the user location and I have no control over the database query

问题回答

Use timestamp with time zone in UTC in your database

For a point in time in your database use UTC, universal time. And to make sure that your database knows that it is in UTC, use timestamp with time zone data type.

你可能认为,在你的地方时间区美国/芝加哥,储存时间更简单,更适合你的目的。 再次思考。 虽然你的意图目前是为这个时区设计的,但谁能保证将来某个时候美国其他地方的用户不会使用它? 您的编码未能在其他一些方案中重新使用? 如果学校项目要在考试后退学,学校项目就是一个很好的培训最佳做法的地方。 这里的最佳做法是储存UTC时间。

如果进一步使用<代码>无时区/代码>或<代码> > 日,数据库中可能存在一个小的问题,即美国/芝加哥时区的时间有时不明确。 每年11月初,午餐时间结束, clo折又一小时。 例如,去年11月5日,2个大坝被退回到1个,尽管早一个小时已经达到1个。 因此,当你在夜间从数据库中抽取1至2天的时间时,你无法知道夏季时间或标准时间是否打算。 同样,这种时代必定相互混淆。 UTC不使用夏天时间,因此, has子没有处理这个问题。

不同的房舍管理处对<代码>与时区有不同的概念。 页: 1 另一些公司在UTC储存时间,必要时从一些当地时间区转而储存和回收,实际上只给我们“UTC时区”的罚款。 我建议,你总是把0(零)冲销。 然而,有几个人允许你储存一个时间区,例如<代码>America/Chicago。 此处使用<代码>Etc/UTC。 在任何情况下,均按您的目的处以罚款。

java.time

我的理解是,你要求在美国/芝加哥时区储存时间。 因此,将<代码>OffsetDatetime与正确的UTC(6或5小时)相加的“UTC”号编码储存在“DB2”“带时间区> 其他房舍管理处的日间,则由其他单位决定,储存<条码>当地日。 首先,请从<代码>XGregorianCalendar上转换。 权利:

/**
 * For this code example I am assuming that a date without time is stored as the start of day
 * and a date with time requires a UTC offset.
 * In both cases I am converting to America/Chicago time zone.
 */
public static OffsetDateTime convertXmlgcToOdt(XMLGregorianCalendar value) {
    if (value.getHour() == DatatypeConstants.FIELD_UNDEFINED
            && value.getMinute() == DatatypeConstants.FIELD_UNDEFINED
            && value.getSecond() == DatatypeConstants.FIELD_UNDEFINED
            && value.getFractionalSecond() == null) { // Date only
        return value.toGregorianCalendar()
                .toZonedDateTime()
                .toLocalDate()
                .atStartOfDay(ZONE_ID)
                .toOffsetDateTime();
    } else { // date and time
        if (value.getTimezone() == DatatypeConstants.FIELD_UNDEFINED) {
            throw new IllegalArgumentException("value must have UTC offset ("timezone")");
        }
        return value.toGregorianCalendar()
                .toZonedDateTime()
                .withZoneSameInstant(ZONE_ID)
                .toOffsetDateTime();
    }
}

洞穴:即使“XMLGregorianCalendar和OffsetDatetime都精准,但我的转换具有微秒。 如果你需要保持XML的精度,我建议:

        OffsetDateTime converted = OffsetDateTime.parse(value.toString());
        return converted.atZoneSameInstant(ZONE_ID)
                .toOffsetDateTime();

Let’s try the conversion method out:

    XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar("2024-02-09T01:57:33.240-06:00");
    System.out.println(convertXmlgcToOdt(xmlDate));
    xmlDate = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar("2024-02-09");
    System.out.println(convertXmlgcToOdt(xmlDate));

Output:

2024-02-09T01:57:33.240-06:00
2024-02-09T00:00-06:00

如果需要改成<条码>当地日,则以<条码>至OffsetDetetime(<>>/条码>和<条码>取代每一条线路;

储存在你的数据库中使用像以下的东西,假定你们正在使用日本银行:

    OffsetDateTime odt = convertXmlgcToOdt(xmlDate);
    PreparedStatement pStmt = yourDatabaseConnection
            .prepareStatement("insert into your_table(your_tstz_column) values(?);");
    pStmt.setObject(1, odt);
    pStmt.executeUpdate();

如果使用<条码>日间断时间区,因此<条码> 当地日,仅通过<条码> 当地日至<条码>。

For really old Java versions

If using Java 6 or 7, use the backport of java.time named ThreeTen Backport, link at the bottom. In this case you can’t directly pass the java.time objects to your PreparedStatement. One option is to format into strings that you pass to PreparedStatement.setString(). If using Java 5, use Joda-Time in a similar manner.

Control the time zone via the database session

If for some reason I can’t guess you are forced to use one of the problematic and outdated Date classes, use the conversion you already have. Configure your database session to use America/Chicago time zone. I don’t understand the logic in this configuration belonging to the session, to me it rather belongs to the database column; but most SQL databases offer it as a setting on the session. Search for how it’s done with your brand of database engine/RDBMS. I include a link for DB2 below to get you started. The DB2 “session time zone” is a mere offset from UTC, so when dealing with times in both standard time and summer time, you will need to set it for each value stored.

www.un.org/Depts/DGACM/index_spanish.htm 或者通过科索沃信托公司违约时区: 真正的 d脏解决办法是,将你的证书的缺省定在独立于服务器的本组织时区之外。 认识到这将影响整个 Java方案,并可能对该方案的其他部分产生意外影响。 我期望它控制用于将<代码>Date转换为timestamp/code>数据类型的时间区,尽管(我尚未测试)。

Either start your server program with a command line option for the purpose, like for example:

java -Duser.timezone=America/Chicago YourApp

Or set the property from within your code, before doing any date and time work:

    System.setProperty("user.timezone", "America/Chicago");

If all else fails, tell a lie

如果在您的设置中没有任何上述内容可行,你需要一种办法,以弥补以下事实:你的服务器、证书和你的数据库对时间区有分歧,因此,在储存时对ate进行错误的转换。 我认为,你在自己的答复中所用的骗子似乎奏效,但只有你知道,我们正在做的是故意不正确的转换<>/em>,以弥补我们在储存时从我们的控制下进行的相反不正确的转换。 如果是我的话,我想在守则中阐明这一点,或者今后读到该守则的人可能会被严重混淆,并可能试图“纠正”他们可能认为的无意错误。 您可以自行转换或排雷,或 mix。 这里的地雷:

/**
 * Convert to America/Chicago time zone
 * and then convert further to a {@code Date} that when interpreted
 * in the default time zone of the JVM
 * has the same date and time of day (wall-clock time)
 * no matter if this makes the point in time wrong.
 * We are doing a <em>deliberately incorrect conversion</em> to compensate
 * for the opposite incorrect conversion taking place out of our control when
 * storing the {@code Date}.
 * That incorrect conversion happens because the JVM and the database
 * disagree about time zone:
 * the JVM uses UTC (GMT), but the database column must be in America/Chicago time zone.
 */
public static Date convertDate(XMLGregorianCalendar value) {
    if (value == null) {
        return null;
    } else {
        ZonedDateTime dateTimeWithDeliberatelyWrongTimeZone;
        if (value.getHour() == DatatypeConstants.FIELD_UNDEFINED
                && value.getMinute() == DatatypeConstants.FIELD_UNDEFINED
                && value.getSecond() == DatatypeConstants.FIELD_UNDEFINED
                && value.getFractionalSecond() == null) { // Date only
            dateTimeWithDeliberatelyWrongTimeZone = value.toGregorianCalendar()
                    .toZonedDateTime()
                    .toLocalDate()
                    .atStartOfDay(ZoneId.systemDefault());
        } else { // date and time
            if (value.getTimezone() == DatatypeConstants.FIELD_UNDEFINED) { // No UTC offset
                // In this case the no-arg toGregorianCalendar() uses the JVM default time zone.
                // which already gives us the incorrect result we are after.
                dateTimeWithDeliberatelyWrongTimeZone = value.toGregorianCalendar()
                        .toZonedDateTime();
            } else {
                dateTimeWithDeliberatelyWrongTimeZone = value.toGregorianCalendar()
                        .toZonedDateTime()
                        .withZoneSameInstant(ZONE_ID)
                        // Preserve date and time of day
                        // when converting to default time zone
                        .withZoneSameLocal(ZoneId.systemDefault());
            }
        }
        return Date.from(dateTimeWithDeliberatelyWrongTimeZone.toInstant());
    }
}

如美洲金枪鱼委时区现有的那样,将同样的两个<代码>XMLGregorianCalendar的物体转换为:

Fri Feb 09 01:57:33 UTC 2024
Fri Feb 09 00:00:00 UTC 2024

而且,我们在<代码>中未作任何抵销。 XMLGregorianCalendar :

    xmlDate = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar("2024-02-09T01:57:33.240");
Fri Feb 09 01:57:33 UTC 2024

参看<代码>Date物体在UTC上印。 由于时间是预期的,这意味着<代码>。 日期从科技委起为6小时,因此不正确。 日期和印刷时间也是存放在数据库的日期和时间,这是你想要的。

Links

tl;dr

如果递交了<条码>XMLGregorianCalendar,即改为现代类别。

myXmlGregCal
    .toGregorianCalendar()
    .toZonedDateTime()
    .withZoneSameInstant( 
        ZoneId.of( "America/Edmonton" ) 
    )
    .format (
        DateTimeFormatter
            .ofLocalizedDateTime( FormatStyle.FULL )
            .withLocale( Locale.GERMANY )
    )

如果在标准,ISO 8601/a>格式,但从中央中央直辖区获得抵消,其次为OffsetDatetime

OffsetDateTime
    .parse( "2024-02-09T01:57:33.240-06:00" ) 
    .atZoneSameInstant( 
        ZoneId.of( "Pacific/Auckland" )
    )
    .format (
        DateTimeFormatter
            .ofLocalizedDateTime( FormatStyle.FULL )
            .withLocale( Locale.GERMANY )
    )

Convert a XMLGregorianCalendar to a java.util. 日期,java.time:

java.util.Date
    .from(
        myXmlGregCal
            .toGregorianCalendar()
            .toZonedDateTime()
            .toInstant()
    )

Details

你们正在使用可怕的、有缺陷的、现存的日间班。 避免XMLGregorianCalendar ,GregorianCalendar,Calendar,SimpleDateFormat and both Date 。 几年前,他们被现代的java.time级植根于第310号行政指示。

有许多缺陷是:java.util.Date#toString存在于你身上。 这种方法干扰了科索沃信托机构目前的违约时区,同时产生代表该物体的美国贸总会价值的案文。

When handed a XMLGregorianCalendar object, immediately convert to its modern replacement, java.time.ZonedDateTime by way of java.util.GregorianCalendar.

ZonedDateTime zdt = myXmlGregCal.toGregorianCalendar().toZonedDateTime() ;

如果你想要调整这个时间,以在不同的时间区看到,则适用<代码>ZoneId,以生产另一个<代码>ZonedDatetime。 <>java.time 课程为:,因此,你获得了一个新的物体,而不是改动原来的物体。

ZoneId zTokyo = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdtTokyo = zdt.withZoneSameInstant( zTokyo ) ;

形成地方化案文。

Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale ) ;
String output = zdtTokyo.format( f ) ;

如果您需要以<条码>代表时间。 ZonedDatetime as a java.util.Date to interoperation with original code not yet updated to java.time, 摘录Instant。 至java.util.Date. from 。 http://www.ohchr.org。 日期:代表了时间表的一个要点,从美洲金枪鱼委中减去零时段。 遗产阶级决心冲锋枪,而现代阶级则决心去除。

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.Date;
import java.util.TimeZone;

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;

import java.sql.Timestamp;
import java.time.ZoneId;

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;

public class Demo {



    public static final ZoneId ZONE_ID = ZoneId.of("America/Chicago");
    public static Date convertDate2(XMLGregorianCalendar myXmlGregCal) {
        ZonedDateTime zdt = myXmlGregCal.toGregorianCalendar().toZonedDateTime();
        ZoneId zChicago = ZoneId.of("America/Chicago");
        ZonedDateTime zdtChicago = zdt.withZoneSameInstant(zChicago);
        Locale locale = Locale.US;
        DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(locale);
        String output = zdtChicago.format(f);

        // Parse the output string to LocalDateTime
        LocalDateTime localDateTime = LocalDateTime.parse(output, f);

        // Convert LocalDateTime to Date
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    public static Date convertDate(XMLGregorianCalendar value) {
        if (value == null) {
            return null;
        } else {
            if (value.getXMLSchemaType() == DatatypeConstants.DATE) {
                return value.toGregorianCalendar().getTime();
            } else {
                LocalDateTime localDateTime = value.toGregorianCalendar().toZonedDateTime().withZoneSameInstant(ZONE_ID).toLocalDateTime();
                return Timestamp.valueOf(localDateTime);
            }
        }
    }

    public static void main(String[] args) {
        try {
            // Parse the XML date string into XMLGregorianCalendar
            XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2024-02-09T01:57:33.240-06:00");
            // Convert XMLGregorianCalendar to Date
            Date date = convertDate(xmlDate);
            // Print the result
          //  System.out.println("Date: " + date);
            System.out.println(convertDate2(xmlDate));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

概述:

阅读日期从XML开始,假定它在美洲金枪鱼委的时间区。

将美洲金枪鱼委的时间区改为“America/Chicago”的时间区。

在数据库中储存“America/Chicago”时间区。

在从数据库中检索日期时,将其改为“America/Chicago”时段。

 public class Demo {
public static final TimeZone TIMEZONE = TimeZone.getTimeZone("America/Chicago");

// Convert XML date to "America/Chicago" timezone date
public static Date convertXmlDateToChicagoTime(XMLGregorianCalendar value) {
    if (value == null) {
        return null;
    } else {
        // Convert XML date to Date object
        Date date = value.toGregorianCalendar().getTime();
        // Set the timezone of the Date object to UTC
        value.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
        // Convert Date object to "America/Chicago" timezone date
        return convertDateToTimezone(date, TIMEZONE);
    }
}

// Convert database date to "America/Chicago" timezone date
public static Date convertDbDateToChicagoTime(Date date) {
    return convertDateToTimezone(date, TIMEZONE);
}

// Convert date to the specified timezone
private static Date convertDateToTimezone(Date date, TimeZone timezone) {
    long timestamp = date.getTime();
    int offset = timezone.getOffset(timestamp);
    return new Date(timestamp - offset);
}

public static void main(String[] args) {
    try {
        // Assume the date read from XML is "2024-02-09T01:57:33.240-06:00"
        XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2024-02-09T01:57:33.240-06:00");
        // Convert XML date to "America/Chicago" timezone date
        Date chicagoTimeDate = convertXmlDateToChicagoTime(xmlDate);
        // Store chicagoTimeDate into the database...

        // Assume the date retrieved from the database is chicagoTimeDate
        Date retrievedDbDate = chicagoTimeDate;
        // Convert the date from the database to "America/Chicago" timezone date
        Date retrievedChicagoTimeDate = convertDbDateToChicagoTime(retrievedDbDate);

        // Now you can use retrievedChicagoTimeDate, which is represented in "America/Chicago" timezone
        System.out.println("Retrieved Date in Chicago Time: " + retrievedChicagoTimeDate);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

该守则确保,不论从XML中读出日期的时间长短,都正确改为“America/Chicago”时间。 同样,从数据库检索的日期将在“America/Chicago”时间区退回,确保一致性。

Java Demo Class:

import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;

import javax.xml.datatype.DatatypeFactory;
import java.util.Date;

import java.sql.Timestamp;
import java.time.ZoneId;

public class Demo {

  public static final ZoneId ZONE_ID = ZoneId.of("America/Chicago");
  public static final ZoneId ZONE_ID_UTC = ZoneId.of("UTC");

  public static Date convertDate2(XMLGregorianCalendar value) {

    ZonedDateTime dateTimeWithDeliberatelyWrongTimeZone;

    if (value.getTimezone() == DatatypeConstants.FIELD_UNDEFINED) {
      dateTimeWithDeliberatelyWrongTimeZone = value.toGregorianCalendar()
        .toZonedDateTime()
        .withZoneSameInstant(ZONE_ID_UTC) // Assume UTC time
        .withZoneSameLocal(ZONE_ID); // Convert to CST
    } else {
      dateTimeWithDeliberatelyWrongTimeZone = value.toGregorianCalendar()
        .toZonedDateTime()
        .withZoneSameInstant(ZONE_ID)
        // Preserve date and time of day when converting to default time zone
        .withZoneSameLocal(ZoneId.systemDefault());
    }
    return Date.from(dateTimeWithDeliberatelyWrongTimeZone.toInstant());
  }

  public static Date convertDate(XMLGregorianCalendar value) {
    if (value == null) {
      return null;
    } else {
      if (value.getXMLSchemaType() == DatatypeConstants.DATE) {
        return value.toGregorianCalendar().getTime();
      } else {
        LocalDateTime localDateTime = value.toGregorianCalendar().toZonedDateTime().withZoneSameInstant(ZONE_ID).toLocalDateTime();
        return Timestamp.valueOf(localDateTime);
      }
    }
  }

  public static void main(String[] args) {
    try {
      // Parse the XML date string into XMLGregorianCalendar
      XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar("2024-02-09T01:57:33.240");
      // Convert XMLGregorianCalendar to Date
      Date date = convertDate(xmlDate);
      // Print the result
      // System.out.println("Date: " + date);
      System.out.println(convertDate2(xmlDate));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签