我从Angular应用程序将日期作为字符串发送到服务器,并转换为javadate
对象存储在数据库中。
还从UI发送timezoneoffset
以便在转换时使用客户端的时区。(在谷歌搜索后,我发现这种方法可以根据用户位置获得正确的结果)
编写了以下代码进行转换:
public static void main(String args[]) throws ParseException {
String inputDate = "04/05/2018"; // This date coming from UI
int timeZoneOffset = -330; // This offset coming from UI
// (new Date().getTimeZoneOffset())
getDate(inputDate, timeZoneOffset);
}
public static Date getDate(String inputDate, int timeZoneOffset)
throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(-timeZoneOffset * 60);
System.out.println("Default time zone: " + TimeZone.getDefault().getID());
TimeZone timeZone = TimeZone.getTimeZone(zoneOffset);
System.out.println("Time zone from offset: " + timeZone.getID());
dateFormat.setTimeZone(timeZone);
Date date = dateFormat.parse(inputDate);
System.out.println("Converted date: " + date);
return date;
}
默认时区:America/New_York
从偏移量开始的时区:GMT+05:30
转换日期:2018年4月5日Thu 00:00:00
服务器中的实际结果:
默认时区:America/New_York
从偏移量开始的时区:GMT+05:30
转换日期:美国东部时间2018年4月4日Wed 14:30:00
为什么即使我设置了用户的时区,日期也减少到一天?我是一个新的日期和时间相关的概念,我谷歌了几次没有找到答案,可以有人请帮助这一点。
提前致谢
戈弗雷的答案是正确的。
LocalDate.parse(
"04/05/2018" ,
DateTimeFormatter.ofPattern( "MM/dd/uuuu" )
)
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
.toString()
2018-04-05T00:00+05:30“亚洲/加尔各答”
对于数据库中的存储,请使用UTC。
当印度新的一天开始时,世界协调时的日期仍然是“昨天”,所以4月4日而不是4月5日。同一个时刻,时间线上的同一个点,不同的挂钟时间。
LocalDate.parse(
"04/05/2018" ,
DateTimeFormatter.ofPattern( "MM/dd/uuuu" )
)
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
.toInstant()
2018-04-04T18:30:00Z
您正在使用糟糕的旧日期-时间类,这些类已经被证明是设计不良、令人困惑和麻烦的。现在它们被java.time类所取代。
ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(-timeZoneOffset * 60);
…
TimeZone timeZone = TimeZone.getTimeZone(zoneOffset);
您将现代类(ZoneOffset
)与麻烦的遗留类(TimeZone
)混合在一起。不要将现代类与遗留类混合使用。忘记所有旧类,包括date
、calendar
和simpledateformat
。java.time类被设计为完全替代遗留类。
使用zoneid
(和zoneoffset
)代替timezone
。
String input = "04/05/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;
偏离UTC不是时区。偏移量只是从UTC位移的小时数、分钟数和秒数。您对变量名的选择表明在这一点上可能存在混淆。
ZoneOffset offset = ZoneOffset.of( -3 , 30 ) ;
时区是一个特定地区的人们使用的过去、现在和将来偏移变化的历史。所以时区总是比偏移量更好。
以大陆/地区
格式指定适当的时区名称,例如美国/蒙特利尔
、非洲/卡萨布兰卡
或太平洋/奥克兰
。切勿使用est
或ist
等3-4个字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // India time zone. Currently uses offset of +05:30 (five and a half hours ahead of UTC).
你的目标似乎是在那个区域的约会的第一个时刻。让java.time来确定当前第一个时刻。不要假设时间是00:00:00。在某些地区的某些日期,一天可能从另一个时间开始,例如01:00:00。
ZonedDateTime zdt = ld.atStartOfDay( z ) ; // Determine the first moment of the day on this date in this zone. Not always 00:00:00.
作为为什么应该使用时区而不是仅仅使用偏离-UTC的示例,请查看-330
的示例数据,我可能很容易将其曲解为落后UTC三个半小时。此偏移量当前仅在区域America/ST_Johns
中使用,并且仅在一年中的部分时间在那里使用。因此,如果您将-03:30的偏移量应用于一年中错误的某一天,那么您的结果将是无效的,但不会被检测到。
但是您的示例缺少时区,所以让我们使用offset-from-UTC而不是zone。
使用int
整数来表示offset-from-UTC是一种错误的类型选择。首先是模棱两可。这个-330
可能会被解释为在-03:30
偏移量落后计划三个半小时的情况下进行的一次笨拙的尝试。其次,它使解析变得比需要的更棘手。第三,作为一个分钟数,它忽略了与秒相抵消的可能性。第四,对于UTC前面的偏移量使用负数(显然),尽管常见用法和标准用法是相反的。最后,它忽略了ISO 8601设定的将偏移表示为文本的明确标准:±hh:mm:ss
(和变体)。顺便说一下,填充零在标准中是可选的,但我建议总是包含,因为各种库和html" target="_blank">协议都期望它。
您的意图似乎是整数预期的分钟数。
long seconds =( TimeUnit.MINUTES.toSeconds( - 330 ) * -1 ); // Multiply by negative one to flip the sign to standard ISO 8601 usage, where `+` means “ahead* of UTC and `-` means *behind* UTC.
秒数:19800
ZoneOffset offset = ZoneOffset.ofTotalSeconds( ( int ) seconds );
最后一步:在这个偏移量中得到一天的第一时刻。注意:由于缺少时区,我们不确定此偏移在此日期是否有效。
从返回的zoneddatetime
转换为offsetdatetime
。如上所述,确定一天中的第一个时刻应始终使用时区来完成,从而得到zoneddatetime
。我们违反了使用偏移量的合理做法,但是使用返回的zoneddatetime
对象会产生误导,因为我们的对象缺少真正的时区,并且只有一个偏移量。因此,offsetdatetime
类使我们的意图更加清晰,使代码更加自文档化。
OffsetDateTime odt = ld.atStartOfDay( offset ).toOffsetDateTime();
同样,这种使用偏移量的方法并不推荐,因为您应该从用户那里收集一个时区名称作为输入,而不是偏移量。
通常最好以UTC存储时刻。
从offsetdatetime
或zoneddatetime
中提取instant
以获得与UTC相同的时刻。
Instant instant = zdt.toInstant() ;
2018-04-04T18:30:00Z
Java.time框架内置在Java8和更高版本中。这些类取代了麻烦的旧的遗留日期-时间类,如java.util.date
、Calendar
、&SimpleDateFormat
。
要了解更多信息,请参阅Oracle教程。并搜索堆栈溢出以获得许多示例和解释。规范是JSR310。
您可以直接与数据库交换java.time对象。使用与JDBC4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用额外的类扩展了java.time。这个项目是将来可能添加java.time的一个试验场。您可以在这里找到一些有用的类,如interval
、yearweek
、yearquard
等等。
问题内容: 我的时区有日期,我想将其转换为另一个时区,例如我的日期为“ 2013年3月15日下午3:01:53 PM”,位于时区“ GMT-06:00”。我想在“ GMT-05:00”时区进行转换。我的搜索量很多,对日期的实际工作方式感到困惑。如何将时区应用于日期。我尝试使用SimpleDateFormat,日历和偏移量。 它返回输出 。我想应该是 ,因为时间是在’GMT-06:00’时区,所以在
问题内容: 该java.util.Date 方法显示当地时区的日期。 在几种常见的情况下,我们希望以UTC格式打印数据,包括日志,数据导出以及与外部程序的通信。 在UTC中创建String表示形式的最佳方法是什么? 如何用更好的格式替换无法排序的juDate 格式(感谢@JonSkeet!)? 附录 我认为以自定义格式和时区打印日期的标准方法非常繁琐: 我一直在寻找像这样的单线: 问题答案: 遵循
问题内容: 我需要有关此java方法的一些建议。此方法的目的是采用表示日期的字符串-该字符串是从EST时区中的日期创建的-并将其转换为UTC时区中的java Date对象。 我看到的问题是dt的值似乎已关闭。例如,如果dateString为‘10 / 16/2012 12:06 PM’-我期望dt(以UTC为单位)的值类似于“ 2012年10月16日,星期二,下午4:06”。取而代之的是,dt的值
我正在与它的时区约会,我想把它转换成另一个时区,例如。我的日期是“3/15/2013 3:01:53 PM”,它位于时区“GMT-06:00”。我想在'GMT-05:00'时区转换这个。我有很多搜索,我不知道实际约会是如何运作。如何将时区应用到日期。我尝试过SimpleDateFormat、Calender和Offset。 它返回输出。我猜应该是,因为时间在'GMT-06:00'时区,所以应该是H
我有一些日期格式的字符串,例如 我使用SimpleDateForate并尝试将String类型转换为Date类型。它将String类型转换为Date类型,但是Java无法识别时区“MYT”,而是将其设置为计算机的默认时区,即“CST”。我需要在Date对象中记录时区。我该怎么做?
问题内容: 我在mysql中使用NOW()获取当前日期和时间。我想将日期值转换为varchar并将其与另一个字符串连接。我该怎么做? 问题答案: 使用DATE_FORMAT()