java中不同时区的日期差异

时间:2018-03-17 08:31:43

标签: java datetime google-app-engine timezone date-difference

我在实际上从表中构建嵌套的JSON。 Json看起来像这样:

{"date":"03-16-2018 06:57:02",
 "details":
    [  
        {  
           "motorstate":0,
           "startTime":"03-16-2018 20:41:57",               
        },
        {  
           "motorstate":0,
           "startTime":"03-16-2018 06:57:02",               
        }
     ]
},
{"date":"03-15-2018 08:08:48",
"details":
   [  
        {  
           "motorstate":0,
           "startTime":"03-16-2018 03:53:30",
        }
   ]
}

如果你看一下上面的例子,第二条记录:

{"date":"03-15-2018 08:08:48",
"details":
   [  
        {  
           "motorstate":0,
           "startTime":"03-16-2018 03:53:30",
        }
   ]
}

日期不匹配。这是因为此处显示的日期是IST,但实际上是以我的Google数据存储区的UTC格式存储的。在UTC中,它仍然是03-15-2018而不是03-16-2018。

我的问题是我们如何在Java中的UTC以外的不同时区执行日期差异? Date.getTime()方法总是给出UTC的差异而不是本地时区。

3 个答案:

答案 0 :(得分:3)

TL;博士

  

java中不同时区的日期差异

Period.between(
    LocalDateTime.parse(
         "03-15-2018 08:08:48" , 
         DateTimeFormatter.ofPattern( “MM-dd-uuuu HH:mm:ss” )
    )
    .atZone( ZoneId.of( ”Asia/Kolkata" )  ) 
    .toLocalDate()
    ,
    LocalDate.now( ZoneId.of( ”Asia/Kolkata" ) )
)

详细

现代方法使用 java.time 类而不是麻烦的旧版旧日期时间类,例如DateCalendar

提示:将日期时间值序列化为文本时,请避免使用自定义格式设置模式。仅使用标准ISO 8601格式。

提示:在将日期时间值作为文本进行交换时,请始终包含偏离UTC和时区名称的指示符。

首先,将输入字符串解析为LocalDateTime,因为它们没有偏移或区域的任何指示。

定义格式化模式以匹配输入。

DateTimeFormatter f = DateTimeFormatter.ofPattern( “MM-dd-uuuu HH:mm:ss” ) ;

解析。

String input = "03-15-2018 08:08:48" ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

您声称知道这些输入旨在代表印度时刻的一个时刻。应用ZoneId获取ZonedDateTime

ZoneId z = ZoneId.of( ”Asia/Kolkata" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

要获取仅限日期的值,请提取LocalDate

LocalDate ld = zdt.toLocalDate() ; 

要将日期之间的差值表示为未附加到时间线的年数,月数和天数,请使用Period

Period p = Period.between( ldt , LocalDate.now( z ) ) ;

总天数。

long days = ChronoUnit.DAYS.between( start , stop ) ;

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& 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)

以下方法会将您的UTC时间返回到当前时区,这对我有用

  public static Date getLocalDateObjFromUTC(String date, String time) throws ParseException {
    String dateAndTimeInUTC = date + " " + time;
    SimpleDateFormat localDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    localDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date dateInLocalTimeZone = localDateFormat.parse(dateAndTimeInUTC);
    return dateInLocalTimeZone;
}

答案 2 :(得分:0)

public String getSummary(String deviceGuid)
{
    Query<com.google.cloud.datastore.Entity> query 
        = Query.newEntityQueryBuilder()
            .setKind("sensordata")
            .setFilter(PropertyFilter.eq("deviceguid", deviceGuid))
            .setOrderBy(OrderBy.desc("startTime"))
            .build();

    QueryResults<com.google.cloud.datastore.Entity> resultList = 
  datastore.run(query);
    if(!resultList.hasNext())
    {           
        log.warning("No record found..");
        return "No record found";
    }

    com.google.cloud.datastore.Entity e =null;
    com.google.cloud.datastore.Entity pe =null;

    SensorDataOut sensorDataOut = new SensorDataOut();
    SensorSummaryDataOut summary = new SensorSummaryDataOut();
    TotalSummaryDataOut totalSummary = new TotalSummaryDataOut();


    Calendar calendar = Calendar.getInstance();
    calendar.setTimeZone(TimeZone.getTimeZone("IST"));

    Calendar calendar1 = Calendar.getInstance();
    calendar1.setTimeZone(TimeZone.getTimeZone("IST"));


    SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("IST"));

    SimpleDateFormat sdf1 = new SimpleDateFormat("MM-dd-yyyy");
    //sdf.setTimeZone(TimeZone.getTimeZone("IST"));



    long stopTime;
    long startTime;
    long pStartTime;
    long diffTime;
    long diffDay;
    Date pDateWithoutTime;
    Date eDateWithoutTime;

    while(resultList.hasNext())
    {
        e = resultList.next();

        startTime  = (e.contains("startTime"))?e.getTimestamp("startTime").toSqlTimestamp().getTime():0;
        stopTime  = (e.contains("stopTime"))?e.getTimestamp("stopTime").toSqlTimestamp().getTime():0;   
        //log.info("Start Date : " + e.getTimestamp("startTime").toString() + " - " +  String.valueOf(startTime));
        //log.info("Stop Date : " + e.getTimestamp("stopTime").toString() + " - " + String.valueOf(stopTime));
        //log.info("Usage Volume :" + String.valueOf(e.getLong("usageVolume")));

        sensorDataOut = new SensorDataOut();

        calendar.setTimeInMillis(stopTime);                                             
        sensorDataOut.stopTime = sdf.format(calendar.getTime());

        calendar.setTimeInMillis(startTime);                                    
        sensorDataOut.startTime = sdf.format(calendar.getTime());


        sensorDataOut.motorstate    = (e.contains("motorstate"))?(int)e.getLong("motorstate"):-1;
        sensorDataOut.startVolume   = (e.contains("startVolume"))?(int)e.getLong("startVolume"):-1;
        sensorDataOut.stopVolume    = (e.contains("stopVolume"))?(int)e.getLong("stopVolume"):-1;
        sensorDataOut.usageTime     = (e.contains("usageTime"))?e.getLong("usageTime"):-1;
        sensorDataOut.usageVolume   = (e.contains("usageVolume"))?(int)e.getLong("usageVolume"):-1;

        if(pe!=null)
        {               
            //Get the date difference in terms of days. If it is same day then add the volume consumed
            pStartTime= pe.getTimestamp("startTime").toSqlTimestamp().getTime();
            try{
                calendar.setTimeInMillis(pStartTime);
                pDateWithoutTime = sdf1.parse(sdf1.format(calendar.getTime()));

                calendar1.setTimeInMillis(e.getTimestamp("startTime").toSqlTimestamp().getTime());
                eDateWithoutTime = sdf1.parse(sdf1.format(calendar1.getTime()));    


            }
            catch(Exception ex){
                log.info("Exception while parsing date");
                continue;
            }


            diffTime = Math.abs(pDateWithoutTime.getTime() - eDateWithoutTime.getTime());
            diffDay = TimeUnit.DAYS.convert(diffTime, TimeUnit.MILLISECONDS);


            //log.info("pDateWithoutTime: " + pDateWithoutTime +  ", eDateWithoutTime: " + eDateWithoutTime + ", consumedVolume: " 
            //          + sensorDataOut.usageVolume;


            if(diffDay!=0) //If not same day
            {
                totalSummary.totVolume = totalSummary.totVolume + summary.totVolume;
                totalSummary.totDuration = totalSummary.totDuration + summary.totDuration;                  
                totalSummary.details.add(summary);
                summary = new SensorSummaryDataOut();                   
            }

        }

        summary.date = sensorDataOut.startTime;         
        summary.totVolume = summary.totVolume + sensorDataOut.usageVolume;
        summary.totDuration = summary.totDuration + sensorDataOut.usageTime;            
        summary.details.add(sensorDataOut);

        pe = e;
    }

    if(summary.details.size()>0)
    {
        totalSummary.totVolume = totalSummary.totVolume + summary.totVolume;
        totalSummary.totDuration = totalSummary.totDuration + summary.totDuration;                  
        totalSummary.details.add(summary);
        summary = new SensorSummaryDataOut();                   
    }

    totalSummary.avgVolume = totalSummary.totVolume/totalSummary.details.size();
    totalSummary.deviceguid = deviceGuid;

    String json = "";
    Gson gson = new Gson();
    json = gson.toJson(totalSummary);
    return json;

} //End of Function