1

I want to get an Instant object of start and end of the current month. For completeness, I can say that I need them to get some object from the database (Spring data).

Optional<List<Object» findAllByObjectAndStateChangeDateBetween(Object partner, Instant start, Instant end);

Of course, I found this on StackOverflow Start and end date of a current month

But I wrote

begining = calendar.getTime().toInstant();

And have begining = 2020-08-31T19:00:00Z end = 2020-09-30T18:59:59.999Z

Bui i just want begining = 2020-09-01T00:00:01Z end = 2020-09-30T23:59:59.999Z

Ismail
  • 2,322
  • 1
  • 12
  • 26
  • `Calendar` operates in the `TimeZone` assigned to the `Calendar` object, which is the JVM's *default* time zone unless otherwise specified. `Instant` is always in UTC. So the question is: How was the value currently in the `Calendar` object assigned? We'd need to see that code to figure out how to best fix your code. – Andreas Sep 04 '20 at 10:38
  • *FYI:* `getTime()` is unnecessary, `calendar.toInstant()` gives the same result. – Andreas Sep 04 '20 at 10:41
  • This? zone =sun.util.calendar.ZoneInfo[id="Asia/Yekaterinburg",offset=18000000,dstSavings=0,useDaylight=false,transitions=68,lastRule=null] – Семен Немытов Sep 04 '20 at 10:46

1 Answers1

1

To convert a Calendar object to an object of Java 8+ Time API, retaining the field values of the Calendar object, use:

ZonedDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId())

To show how this correctly keeps all the field values:

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Yekaterinburg"));

Calendar cal = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(cal.toInstant(), cal.getTimeZone().toZoneId());
System.out.println("java.util.Date: " + new SimpleDateFormat("MMM d, yyyy, h:mm:ss.SSS a XXX").format(cal.getTime()));
System.out.println("ZonedDateTime : " + DateTimeFormatter.ofPattern("MMM d, uuuu, h:mm:ss.SSS a XXX").format(zdt));

System.out.println();
System.out.printf("%-12s%-20s%s%n", "Field"     , "Calendar"                    , "ZonedDateTime");
System.out.printf("%-12s%-20d%d%n", "Year"      , cal.get(Calendar.YEAR)        , zdt.getYear());
System.out.printf("%-12s%-20d%d%n", "Month"     , cal.get(Calendar.MONTH)       , zdt.getMonthValue());
System.out.printf("%-12s%-20d%d%n", "Day"       , cal.get(Calendar.DAY_OF_MONTH), zdt.getDayOfMonth());
System.out.printf("%-12s%-20d%d%n", "Hour"      , cal.get(Calendar.HOUR_OF_DAY) , zdt.getHour());
System.out.printf("%-12s%-20d%d%n", "Minute"    , cal.get(Calendar.MINUTE)      , zdt.getMinute());
System.out.printf("%-12s%-20d%d%n", "Second"    , cal.get(Calendar.SECOND)      , zdt.getSecond());
System.out.printf("%-12s%-20d%d%n", "Milli/Nano", cal.get(Calendar.MILLISECOND) , zdt.getNano());
System.out.printf("%-12s%-20s%s%n", "Time Zone" , cal.getTimeZone().getID()     , zdt.getZone().getId());
System.out.printf("%-12s%-20s%d%n", "  Offset"  , cal.getTimeZone().getOffset(cal.getTimeInMillis()), zdt.getOffset().getTotalSeconds());

System.out.println();
System.out.println("Instant (same real time) : " + zdt.toInstant());
System.out.println("Instant (same local time): " + zdt.withZoneSameLocal(ZoneOffset.UTC).toInstant());

Output

java.util.Date: Sep 4, 2020, 4:20:32.475 PM +05:00
ZonedDateTime : Sep 4, 2020, 4:20:32.475 PM +05:00

Field       Calendar            ZonedDateTime
Year        2020                2020
Month       8                   9
Day         4                   4
Hour        16                  16
Minute      20                  20
Second      32                  32
Milli/Nano  475                 475000000
Time Zone   Asia/Yekaterinburg  Asia/Yekaterinburg
  Offset    18000000            18000

Instant (same real time) : 2020-09-04T11:20:32.475Z
Instant (same local time): 2020-09-04T16:20:32.475Z

Note how the Calendar month value is 0-based. It's one of the many reasons we don't use it any more.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • and how can I get Instance object? Or I should toInstant() after converting? – Семен Немытов Sep 04 '20 at 11:14
  • @СеменНемытов Instant is always UTC. Do you want the `Instant` to represent the same actual **real** time, i.e. adjusted for the time zone offset? Or do you want an `Instant` value with the same year/month/.../second values, i.e. *ignoring* the time zone? – Andreas Sep 04 '20 at 11:17
  • I just want to get Instant object without time shifts (as I set in calendar). Or maybe you know another way to create Instant ? – Семен Немытов Sep 04 '20 at 11:23
  • @СеменНемытов Answer updated to show how to get `Instant` with same local time, i.e. ignoring time zone offset. – Andreas Sep 04 '20 at 11:25