android เพิ่มหรือลบชั่วโมงจากการประทับเวลาในฐานข้อมูล

ฉันต้องการลบสองสามวันจากการประทับเวลาของฉันใน Android

ฉันมีฐานข้อมูล SQLite ที่มีช่องวันที่เป็นประเภทยาว เมื่อฉันดำเนินการค้นหาโดยที่ฉันพูดว่า date = date - (3 * 86400000) บางครั้งฉันพบความแตกต่างหนึ่งชั่วโมงซึ่งเป็นผลมาจากการแปลงเป็นวันที่ที่อ่านได้

แต่สิ่งนี้เป็นไปได้อย่างไร? มันเกี่ยวข้องกับการประหยัดเวลากลางวันหนึ่งชั่วโมงในเขตเวลาของฉันหรือไม่?

เพราะฉันจะพบว่ามันแปลกถ้านั่นเป็นเหตุผลเพราะคุณกำลังคำนวณด้วยค่ายาวสองค่า และหลังจากแปลงกลับเป็นวันที่และเวลาแล้ว ก็ไม่น่าจะมีปัญหาเรื่องการปรับเวลากลางวันใช่ไหม


person randomizer    schedule 26.10.2012    source แหล่งที่มา
comment
คุณรู้ได้อย่างไรว่าเวลาต่างกันหนึ่งชั่วโมง? คุณกำลังแปลงสิ่งเหล่านี้เป็น Date หรือ Calendar และตรวจสอบหรือไม่ การดูโค้ดตัวอย่างเพื่อดูว่าคุณกำลังทำอะไรอยู่จะเป็นประโยชน์   -  person Steve Blackwell    schedule 27.10.2012
comment
เขตเวลาอาจเป็นปัญหาได้หากมีการตั้งค่ารายการใดรายการหนึ่ง ในขณะที่อีกรายการไม่ได้ตั้งค่าไว้ เนื่องจากวันที่ของ Java มีค่าเริ่มต้นเป็น GMT นั่นจะเป็นพื้นฐานในการพิจารณาว่าใครอยู่ในเขตเวลาใด   -  person dispake    schedule 27.10.2012


คำตอบ (2)


ขอบคุณสำหรับคำตอบ แต่ฉันพบวิธีแก้ไขแล้ว ดูเหมือนว่าเมื่อคุณเพิ่มวันเป็นมิลลิวินาทีลงในการประทับเวลา และมีการตั้งค่าเวลากลางวันที่แตกต่างกันเป็นชั่วโมง วันที่ดังกล่าวจะได้รับการแก้ไขโดยอัตโนมัติ

เมื่อฉันทำสิ่งต่อไปนี้ ชั่วโมงจะถูกละเว้น:

Date d = new Date();
d.setDays(d.getDays() - 2);

อย่างไรก็ตาม ฉันอยากจะแนะนำให้ใช้ไลบรารี Joda เพราะมันมีความยืดหยุ่นและทำงานง่ายกว่า

person randomizer    schedule 29.10.2012
comment
โปรดทราบว่าคลาสวันที่-เวลาเก่าๆ ที่สร้างปัญหาอย่างมาก เช่น java.util.Date, java.util.Calendar, และ java.text.SimpleDateFormat ตอนนี้เป็น แบบเดิม ซึ่งแทนที่ด้วย java.time คลาสที่สร้างใน Java 8 และใหม่กว่า . ดูบทช่วยสอน โดย Oracle - person Basil Bourque; 16.11.2018

tl;dr

ใช้คลาส java.time ที่ทันสมัย

หากคุณหมายถึง 3 วันตามปฏิทิน ให้ทำดังนี้:

Instant                                // Represent a moment in UTC with a resolution of nanoseconds.
.ofEpochSecond( x )                    // Parse some number of whole seconds or milliseconds from the epoch reference of first moment of 1970 in UTC.
.atZone(                               // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
    ZoneId.of( "Pacific/Auckland" )    // Assign the time zone by which you want the context of their calendar for adding dates.
)                                      // Returns a `ZonedDateTime` object.
.plus(                                 // Move to another moment by adding a span-of-time.
    Period.ofDays( 3 )                 // Define a span of time as a number of days on the calendar (date) without regard for the length of a day.
)                                      // Returns another `ZonedDateTime` object.
.toInstant()                           // Adjust from a time zone to UTC. Same moment, different wall-clock time.
.toEpochSeconds()                      // or maybe `toEpochMillis` depending on your practice with your `long` number.

เขียน SQL ของคุณเป็น:

SELECT * FROM event_ WHERE when_ >= ? ;  -- Find events occurring later than the passed moment.

ใน Java ด้วย JDBC 4.2 หรือใหม่กว่า:

myPreparedStatement.setObject( 1 , secondsSinceEpoch ) ;  // Pass seconds calculated above.

การเรียกคืน

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

นับจากยุค

หมายเลขประเภท long ของคุณน่าจะเป็นจำนวนวินาทีทั้งหมดหรือมิลลิวินาทีนับตั้งแต่ วันที่อ้างอิงยุค.

หากยุคที่คุณเลือกนั้นเป็นยุคที่ใช้โดย “เวลา Unix” ซึ่งเป็นช่วงเวลาแรกของปี 1970 ใน UTC, 1970-01-01T00:00:00Z จากนั้นเราสามารถแยกวิเคราะห์ใน Java เป็น Instant. Instant คือช่วงเวลาบนไทม์ไลน์ใน UTC โดยมีความละเอียดระดับนาโนวินาที Instant ภายในคือคู่ของตัวเลข: การนับวินาทีทั้งหมดนับตั้งแต่ยุค บวกเศษส่วนของวินาทีเป็นจำนวนนาโนวินาที

Instant instant = Instant.ofEpochMilli( x ) ;

…or:

Instant instant = Instant.ofEpochSecond( x ) ;

หนึ่งวันไม่ใช่ 24 ชั่วโมง

วันตามวันที่ในปฏิทินไม่เหมือนกับ 24 ชั่วโมง ความผิดปกติในวิธีที่นักการเมืองกำหนดเขตเวลา เช่น เวลาออมแสง (DST) หมายความว่าหนึ่งวันอาจเป็น 23, 23.5, 24, 25 หรือจำนวนชั่วโมง-นาที-วินาทีอื่นๆ

Duration

หากคุณต้องการเพิ่มช่วงเวลา 24 ชั่วโมง ให้ใช้ Duration.

Duration d = Duration.ofDays( 3 ) ;  // `Duration` defines a “day” as being a 24-hours without regard for the calendar dates.

หรือระบุเป็นชั่วโมงซึ่งผลลัพธ์เหมือนกันในคลาส Duration แต่จะชัดเจนมากขึ้นถึงเจตนาและความเข้าใจของคุณ

Duration d = Duration.ofHours( 3 * 24 ) ;  // Same effect as the `Duration.ofDays( 3 )` seen above.

เพิ่มใน Instant ของคุณ

Instant instantLater = instant.plus( d ) ;

Period

หากคุณหมายถึงวันเป็นการเพิ่มวันในปฏิทิน ให้ใช้ Period คลาส ชั้นเรียนนี้แสดงจำนวนปี-เดือน-วัน

Period p = Period.ofDays( 3 ) ;  // `Period` defines a day as a date on the calendar without regard for its length in hours.

เราไม่สามารถเพิ่มสิ่งนั้นลงใน Instant โดยไม่คำนึงถึงปัญหาเขตเวลา หากเพิ่มลงใน Instant ซึ่งอยู่ใน UTC เสมอ เราจะใช้ปฏิทินแบบ UTC ตัวอย่างเช่น การเพิ่มวันลงในค่า UTC อาจแปลเป็น "พรุ่งนี้" ในอินเดียในขณะที่ยังคงเป็น "เมื่อวาน" ในควิเบก เขตเวลาเป็นสิ่งสำคัญในการกำหนดวันที่ ในช่วงเวลาใดก็ตาม วันที่จะแตกต่างกันไปทั่วโลกตามโซน

หากไม่มีการระบุเขตเวลา JVM จะใช้เขตเวลาเริ่มต้นปัจจุบันโดยปริยาย ค่าเริ่มต้นนั้นอาจ เปลี่ยนแปลงได้ตลอดเวลา ระหว่างรันไทม์ (!) ดังนั้นผลลัพธ์ของคุณอาจแตกต่างกันไป ดีกว่าที่จะระบุเขตเวลาที่ต้องการ/คาดหวังอย่างชัดเจนเป็นอาร์กิวเมนต์

ระบุชื่อเขตเวลาที่เหมาะสมในรูปแบบ continent/region เช่น America/Montreal, Africa/Casablanca หรือ Pacific/Auckland . อย่าใช้ตัวย่อ 2-4 ตัวอักษร เช่น EST หรือ IST เนื่องจากไม่ใช่เขตเวลาจริง ไม่ใช่ ไม่ได้มาตรฐาน และไม่ซ้ำกันด้วยซ้ำ(!)

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

หากคุณต้องการใช้เขตเวลาเริ่มต้นปัจจุบันของ JVM ให้ขอและส่งผ่านเป็นอาร์กิวเมนต์ หากละเว้น ค่าเริ่มต้นปัจจุบันของ JVM จะถูกนำไปใช้โดยปริยาย ควรชัดเจนดีกว่า เนื่องจากค่าเริ่มต้นอาจเปลี่ยนแปลงได้ตลอดเวลา ระหว่างรันไทม์ ด้วยโค้ดใดๆ ในเธรดใดๆ ของแอปใดๆ ภายใน JVM

ใช้ ZoneId ของคุณกับ Instant เพื่อรับ ZonedDateTime

ZonedDateTime zdt = instant.atZone( z ) ;

ตอนนี้คุณสามารถเพิ่มวันลงใน ZonedDateTime และปฏิทินที่ผู้คนในภูมิภาคนั้นใช้จะถูกนำมาพิจารณาด้วย

ZonedDateTime zdtLater = zdt.plus( p ) ;  // By “later” we assume the number of days in the `Period` is positive. Alternatively, a `Period` could go backwards in time with a negative number of days.

หากต้องการปรับกลับเป็น UTC ให้แยก Instant เรายังคงมีช่วงเวลาเดียวกัน จุดเดิมบนไทม์ไลน์ แต่มีเวลานาฬิกาแขวนที่แตกต่างออกไป

Instant instantLater = zdtLater.toInstant() ;  // Same moment, different wall-clock time.

เวลาที่ผ่านไประหว่าง zdt ถึง zdtLater อาจเป็นหรือไม่ใช่ ( 3 * 24 ) ชั่วโมง หากการตัดส่วน DST เกิดขึ้นในช่วงเวลานั้น จำนวนชั่วโมงจะเป็น ( ( 3 * 24 ) - 1 ) ใน “Spring Ahead” ในช่วงต้นปี หรือ ( ( 3 * 24 ) + 1 ) ใน “Fall Back” ของฤดูใบไม้ร่วง


เกี่ยวกับ java.time

java.time เฟรมเวิร์กถูกสร้างขึ้นใน Java 8 และใหม่กว่า คลาสเหล่านี้มาแทนที่คลาสวันที่-เวลา ดั้งเดิม แบบเก่าที่ยุ่งยาก เช่น java.util.Date, Calendar, & SimpleDateFormat

โปรเจ็กต์ Joda-Time ขณะนี้อยู่ใน โหมดการบำรุงรักษา แนะนำให้ย้ายไปยัง java.time

หากต้องการเรียนรู้เพิ่มเติม โปรดดูที่บทช่วยสอนของ Oracle. และค้นหา Stack Overflow เพื่อดูตัวอย่างและคำอธิบายมากมาย ข้อมูลจำเพาะคือ JSR 310

คุณสามารถแลกเปลี่ยนวัตถุ java.time กับฐานข้อมูลของคุณได้โดยตรง ใช้ ไดรเวอร์ JDBC ที่สอดคล้องกับ JDBC 4.2 หรือใหม่กว่า ไม่ต้องใช้สตริง ไม่ต้องใช้คลาส java.sql.*

จะรับคลาส java.time ได้ที่ไหน?

โปรเจ็กต์ ThreeTen-Extra ขยาย java.time ด้วยคลาสเพิ่มเติม . โปรเจ็กต์นี้เป็นพื้นที่พิสูจน์ความเป็นไปได้ในการเพิ่ม java.time ในอนาคต คุณอาจพบคลาสที่มีประโยชน์ที่นี่ เช่น Interval, YearWeek, YearQuarter และ เพิ่มเติม

person Basil Bourque    schedule 16.11.2018