Java格式日期到UTC有时会产生' ???? - ?? - ?? T ??:??:??。??? Z'

时间:2018-06-05 18:09:31

标签: c# android simpledateformat android-ksoap2 java-date

在我们的Android应用程序中,我们有一个用于将日期格式化为UTC的util方法:

 static String formatToUTC(Date date) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        return dateFormat.format(date).replace(" ", "T") + "Z";
    }

有时会产生价值:

  

???? - ????Ť??: - :?? ???ž

要解决这个问题,我们应该首先重现它,但我们无法重现这种行为。 我们尝试了不同的Locales并从Long.Max_VALUE,Long.MIN_VALUE传递了一个无效的新Date()。

问题是: 这个问题可能是什么原因?

提前致谢!

编辑:

日期是以两种方式生成的Android应用:

  1. new Date();
  2. new Date(longValue)
  3. 这个日期来自世界各地。

    已编辑2:

    问题出现在服务器端(写在 c#上)。

    我们使用the Ksoap2 for Android与服务器进行交互,它有时会尝试转换 ???? - ?? - ?? T ??:??:??。??? Z < / strong>到DateTime对象。 但主要时间一切都很好。

2 个答案:

答案 0 :(得分:2)

TL;博士

Instant.now().
       .truncatedTo( ChronoUnit.MILLISECONDS ) ;
       .toString()
  

2018-01-23T01:23:45.123Z

线程安全问题?

这是我没有听说过的奇怪行为。我的第一个猜测是线程问题。旧的日期时间类线程安全。他们的替代品 java.time 类完全是线程安全的。

java.time

您可以替换那些麻烦的旧遗留类。几年前它们被现代 java.time 类在Java中取代。对于Android,请参阅下面的项目符号。

Instant

java.util.Date类被java.time.Instant取代。 Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

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

如果只需要毫秒,则可以截断Instant中可能存在的任何微秒或纳秒。

Instant instantTruncated = instant.truncatedTo( ChronoUnit.MILLISECONDS ) ;

ISO 8601

您所需的输出格式由ISO 8601标准定义。

java.time 类在解析/生成字符串时默认使用这些标准格式。因此无需指定格式化模式。

String output = instant.toString();
  

2018-01-23T01:23:45.123Z

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

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

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:0)

为了帮助您找出问题,我会检查返回的String是否包含任何问号,如果确实如此,则抛出异常。在您的例外中设置断路器点,它应该让您确切地看到哪个值打破了您的日期。

有些事情:

static String formatToUTC(Date date) {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    String temp = dateFormat.format(date).replace(" ", "T") + "Z"

    if (temp.contains("?"))
        throw new IllegalArgumentException("Invalid date");  //set a breakpoint here

    return temp;
}

希望这有帮助