我需要为用户在数据库中搜索结果的日期创建一个24小时窗口。用户可以在任何TimeZone中,服务器在PST中,数据库使用mongodb(UTC)。
查找用户发送Wed Dec 21 2016 00:07:11 GMT+0530 (IST)
之类的内容,然后服务器创建具有相同日期和时间的new DateTime()
(默认情况下不会转换为JVM的时区)
我想到的一个解决方法是在用户的时区中使用TimeAtStartOfDay创建一个日期,并为窗口添加addDays加1。
例如:String date = "Wed Dec 21 2016 00:07:11 GMT+0530 (IST)" convert to "2016-12-21 00:00:00.000Z"
注意:服务器在PST中,因此简单的日期对象将无法工作。
如何使用用户的时区(即字符串日期用户传递给BE)在Java中创建Date对象。
答案 0 :(得分:1)
服务器的JVM当前默认时区应与您的编程无关。始终将可选参数中的所需/预期时区传递给各种方法调用。恕我直言,那些时区参数应该是必需的而不是可选的。
我不知道或不使用MongoDB,但this page表示日期时间值的本机类型是aa 64-bit整数,表示自Unix时代以来milliseconds的数量(1970年1月1日)UTC。
仅限日期的值不明确,没有时区的上下文时没有实际意义。对于任何给定的时刻,日期在全球范围内因地区而异。午夜过后几分钟是巴黎法国新的一天,而在加拿大蒙特利尔仍然是“昨天”。
因此,如果需要时区,我们在哪里获得一个?最终,唯一安全可靠的方法是询问用户。以continent/region
格式提醒用户proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
在不询问用户的情况下,您只能假设或猜测。有一些方法可以通过JavaScript检测Web应用程序客户端浏览器的当前默认时区。已经多次讨论Stack Overflow,所以搜索。但是您不确定浏览器区域是由用户向您发出查询的。如果您的用户经过适当的培训,可以采用时区或假设UTC。
区域设置 nothing 与时区有关,仅在生成字符串表示时显示。 Locale
确定(a)用于翻译日期名称,月份名称等的人类语言,以及(b)决定缩写,大小写,标点符号等问题的文化规范。您可以拥有Asia/Kolkata
时区,Locale.CANADA_FRENCH
演示文稿,或Pacific/Auckland
时区,Locale.ITALY
演示文稿。因此,语言环境与此问题无关。
将LocalDate
用于仅限日期的部分。
LocalDate ld = LocalDate.of( 2016 , Month.MARCH , 23 );
提供时区。
ZoneId z = ZoneId.of( "America/Montreal" );
第一时刻开始新的一天。让java.time确定这一点,因为第一个时刻不总是时间00:00:00
。夏令时(DST)等异常可能会导致不同的开始时间。
ZonedDateTime zdtStart = ld.atStartOfDay( z );
我们需要搜索查询的结束时间。通常在日期时间处理中,我们使用半开放方法,其中开头是包含,而结尾是独占。因此,我们希望一天的查询可以运行,但不包括跟随日的第一个时刻。
ZonedDateTime zdtStop = ld.plusDays( 1 ).atStartOfDay( z ); // Or, zdtStart.plusDays( 1 )
显然,MondoDB需要我们将其转换为自UTC时代以来的毫秒数。为此,提取Instant
。
Instant instantStart = zdtStart.toInstant();
Instant instantStop = zdtStop.toInstant();
从那些中提取epoch-count。这可能意味着数据丢失! java.time类以分辨率nanoseconds跟踪值。达到毫秒可能意味着截断一小段时间。
long millisStart = instantStart.toEpochMilli(); // WARNING: possible data loss.
long millisStop = instantStop.toEpochMilli(); // WARNING: possible data loss.