What happened on "2017-9-21 23:59"? - java

I used a calander and add one minute to it each time. but in date "2017-9-21 23:59" something strange happent. The date come one hour back. It's behavior is like date saving time, but that time date saving must not happent.
here is my code and output:
GregorianCalendar fromCalendar = new GregorianCalendar(2017, 8, 21, 22, 58);
for (int i = 0; i < 120; i++) {
System.out.println(fromCalendar.get(Calendar.YEAR) + "-"
+ (fromCalendar.get(Calendar.MONTH) + 1) + "-" + fromCalendar.get(Calendar.DAY_OF_MONTH) + " "
+ fromCalendar.get(Calendar.HOUR_OF_DAY) + ":" + fromCalendar.get(Calendar.MINUTE) + " ");
fromCalendar.add(Calendar.MINUTE, 1);
}
Output:
.
.
.
2017-9-21 23:58
2017-9-21 23:59
2017-9-21 23:0
2017-9-21 23:1
2017-9-21 23:2
.
.
.
Is there any simple point I misunderstood about it?

According to the TimeAndDate.com DST page there is only ONE country in the world where the DST changeover happened at 00:00 on 2017/09/22: Iran
Therefore you must be using the timezone for Iran: Asia/Tehran.

The Answer by Jim Garrison is correct and should be accepted. You are apparently seeing a Daylight Saving Time cut-over for a time zone such as Asia/Tehran.
java.time
You are using troublesome old date-time classes that are now legacy, supplanted by the java.time classes.
Specify a time zone using ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Asia/Tehran" ) ; // Testing the Daylight Saving Time cut-over in Iran.
ZonedDateTime zdt1 = ZonedDateTime.of( 2017 , 9 , 21 , 23 , 59 , 0 , 0 , z ); // Set the moment to what might *appear* be the minute before midnight but is not, is actually an hour and a minute before midnight.
ZonedDateTime zdt2 = zdt1.plusMinutes( 1 ); // Adding a minute takes us to 11 PM again, but with a different offset-from-UTC, for a 25-hours long day.
Dump to console.
System.out.println( "zdt1: " + zdt1 );
System.out.println( "zdt2: " + zdt2 );
See this code run live at IdeOne.com.
zdt1: 2017-09-21T23:59+04:30[Asia/Tehran]
zdt2: 2017-09-21T23:00+03:30[Asia/Tehran]
Notice how adding a minute to roll-over midnight sent us back to 11 PM on the same date but with a different offset-from-UTC, 03:30 versus 04:30. So the 21st of September 2017 in Iran ran 25 hours long.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Related

How to get correct date from a string in Java using SimpleDateFormat?

I am writing an application and have to convert a string into date. The string will have weeks, days and other information, and finally calculate time difference in minutes from that date to current time as shown below. With the code I have, I was expecting to have the "past" object as certain calendar date that was "13 weeks, 2 days, 16 hours, 42 minutes" from current time but what I found surprised me (date object is Tue Mar 24 15:54:00 CST 1970 as of now). Can some one please explain me why my code doesn't work and how to fix that? I referred to the Java Docs but it didn't help me much.
String givenStr = "13 weeks, 2 days, 16 hours, 42 minutes";
SimpleDateFormat format = new SimpleDateFormat("w 'weeks', u 'days', H 'hours', m 'minutes'");
try {
Date past = format.parse(givenStr);
Date now = new Date();
Long minutes = (now.getTime()-past.getTime())/(60*1000);
System.out.printf("Date: %s Minutes: %s\n", past, minutes);
} catch (ParseException ex) {
//DO STH
}
tl;dr
Use standard ISO 8601 formatting for your span-of-time text: P13W2DT16H42M.
Use modern date-time classes found in the java.time framework and in the ThreeTen-Extra library: Instant, PeriodDuration, and Duration.
Instant
.now()
.plus(
PeriodDuration
.parse(
"P" +
"13 weeks, 2 days, 16 hours, 42 minutes"
.replace( " weeks, " , "W" )
.replace( " days, " , "DT" )
.replace( " hours, " , "H" )
.replace( " minutes" , "M" )
)
)
2019-08-18T18:30:42.007034Z
Details
You are conflating two different concepts:
a moment, a point on the timeline
a span-of-time unattached to the timeline
Moment
For a moment, we no longer use the java.util.Date class. That terrible class was supplanted years ago by the java.time.Instant class.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Span-of-time
Your input string does not represent a moment. It represents a span-of-time.
For a span in terms of years-month-days, we use the Period class. For a span in terms of hours-minutes-seconds, we use the Duration.
PeriodDuration
You can combine the two concepts using the PeriodDuration class found in the external library built from the ThreeTen-Extra project. But you should think twice about this. It rarely makes practical sense to combine the two granularities.
But, if you insist, let's give it a go.
First, alter your input string to use standard ISO 8601 format of PnYnMnDTnHnMnS. In this format, the P marks the beginning, and the T separates the coarser granularity from the finer.
String input = "P" + "13 weeks, 2 days, 16 hours, 42 minutes".replace( " weeks, " , "W" ).replace( " days, " , "DT" ).replace( " hours, " , "H" ).replace( " minutes" , "M" ) ;
P13W2DT16H42M
Parse that new input as a PeriodDuration.
PeriodDuration pd = PeriodDuration.parse( input );
Capture the current moment in UTC.
Instant now = Instant.now();
now.toString(): 2019-05-17T01:48:42.007034Z
Add your period-duration to determine a future moment.
Instant later = now.plus( pd );
later.toString(); 2019-08-18T18:30:42.007034Z
If you want a past moment rather than a future moment, call Instant::minus.
Instant earlier = now.minus( pd ) ;
Minutes elapsed
If you want a total number of minutes elapsed between those two moments, use Duration class.
Duration d = Duration.between( now , later ) ;
long minutesTotal = d.toMinutes() ;
minutesTotal: 134922
Time zone
If you want to work with a moment as perceived through the wall-clock time used by the people of a particular region (a time zone), use the ZonedDateTime and ZoneId classes. Call the same named plus/minus methods as seen above.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
ZoneDateTime earlier = now.minus( pd ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

[Android]Get hour from string

Hello I'm trying to convert a string in the format "17:50" to a date in android but when I try to run this code I get the correct hour from the string but the full date is from 1970. I need this date to schedule some local notifications on a given time of the day or in the next day.
String dtStart = "17:50";
SimpleDateFormat format = new SimpleDateFormat("H:mm");
try {
Calendar cal = Calendar.getInstance();
Date date = format.parse(dtStart);
cal.setTime(date);
System.out.println(cal.getTime());
} catch (ParseException e) {
e.printStackTrace();
}
Thu Jan 01 17:50:00 BRT 1970
It's not an error, your code works well. Just if you want to get current date, you have to add the difference between current day and 1st of January 1970.
Your parsed date gives you 17:30 hours, which means 17 * 60 * 60 * 1000 ms + 30 * 60 + 1000 ms.
This way you can find current day: https://stackoverflow.com/a/1908419/4142087
What Anton suggested was correct, and the current day / next day logic is your custom implementation. You have to check current time and if it past that time, jump to setting up the alarm the next day.
java.time
You need a time-of-day class to represent your intended meaning. The legacy date-time classes from the earliest versions of Java lack such a class. The java.sql.Time class pretends to do this, but actually contains a date as well due to poor design decisions.
LocalTime
You want the LocalTime class for a time-of-day value without a date and without a time zone.
It uses a generic 24-hour single-day clock. Adding/subtracting spans of time wraps around the clock since it lacks any concept of dates.
Define a formatting pattern to match your input string.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "H:mm" ) ; // Uppercase `H` means 24-hour clock, lowercase `h` means 12-hour clock.
Parse input string.
String input = "7:50" ;
LocalTime lt = LocalTime.parse( input , f ) ;
Generate a string in standard ISO 8601 format.
String output = lt.toString() ;
07:50
Perhaps your business logic requires assigning the time-of-day to a date. To determine a moment, a point on the timeline, you must also specify a time zone.
LocalDate ld = LocalDate.of( 2018 , Month.MARCH , 27 ) ;
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Months difference using java, to navigate to next or previous page

I've to write a generic code as such, it should give months difference between two dates.
For eg., my input data will be
1. date1 = 22/01/2016
date2 = 30/03/2016
2. date1 = 22/01/2016
date2 = 20/12/2015
based on months difference, I've to move forward(if date2 is future date to date1) or backward(if date2 is past date to date1), those many times.
You could simply compare these two dates as stated here
According to the result you just have to call the same code as if you have clicked on the button yourself (just call the respective mehtod (if you don't use a method for that I would advise you to do so))
Greetings Raven
EDIT:
The difference betweent two dates can be calculated like this
Calendar data = Calendar.getInstance();
Calendar data2 = Calendar.getInstance();
int diff =(int) Math.round(( (data2.getTimeInMillis() - data.getTimeInMillis()) /* ms*/
/ 1000.0 /* seconds*/
/ 3600.0 /*hours*/
/ 24.0 /*days*/
/ 30.0 ))/* monts*/;
With Math.round you ensure months of 31 and 28 days return the right value
Replace data and data2 for your own values
tl;dr
Period.between(
LocalDate.of( 2016 , Month.JANUARY , 22 ) ,
LocalDate.of( 2016 , Month.MARCH , 30 )
).isNegative()
Details
Your Question is not clear, but this might help point you in the right direction.
Avoid the troublesome old date-time classes such as Date that are now legacy, supplanted by the java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
date1 = 22/01/2016
date2 = 30/03/2016
LocalDate start = LocalDate.of( 2016 , Month.JANUARY , 22 ) ;
LocalDate stop = LocalDate.of( 2016 , Month.MARCH , 30 ) ;
Period
Calculate the number of days, months, and years elapsed as a Period.
Period period = Period.between( start , stop ) ;
Test if the stop comes before the start, meaning the elapsed time is negative, going backwards along the timeline.
Boolean isTimeGoingBackwards = period.isNegative() ;
Months
Your comments mention getting a number of months. Understand multiple ways to count months:
Count days elapsed, divided by 30 as the length of a generic month.
Count of calendar months completely covered
Count of calendar months touched by the span of time
Java offers at least some of these. Read the documentation to decide which meets your needs. If going backwards in time, the resulting number is negative.
ChronoUnit.MONTHS
long months = ChronoUnit.MONTHS.between( start , stop ) ;
Period.toTotalMonths
int months = Period.between( start , stop ).toTotalMonths() ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Java Calendar considering hours

Hy guys!
I'm writing a software to keep track of room bookings. Each room has a day of booking, a start time, an end time. The problem is I may have a booking in between two day (eg. from 18-02-2015 23:00 to 19-02-2015).
How can I automate this increasing process without asking the user to insert an end date?
I'm using Calendar for the date but for hours and minutes I just take values from two TextFields.
You could specify the amout of days a room is booked. Then you just have to add the number of days to your first Calendar object.
Working example how to add days in a simple way:
int days = 2; //default duration, placeholder
Calendar now = Calendar.getInstance();
Calendar end = (Calendar) now.clone();
end.add(Calendar.DATE, days);
The Calendar end would then be set the current time in two days.
Normally I wouldn't recommend using Object.clone(), but this answer says it is safe to do so.
There is no way to project a time span with the old Calendar-API (with just one Calendar). But if you could use the new Java 8 Date and Time API, you may use Periods und Durations. They may come in useful, if you need to determine durations for bookings.
However, I can just recommend you to look into the API, since I haven't worked with it enough to provide a useful example.
tl;dr
ZonedDateTime.of( 2015 , Month.FEBRUARY , 18 , 23 , 0 , 0 , 0 , ZoneId.of( "Europe/Paris" ) )
.plus( Duration.ofHours( 3 ) )
2015-02-19T02:00:00+01:00[Europe/Paris]
java.time
The accepted answer uses the outmoded old legacy date-time classes that have proven to be so troublesome and confusing. Now supplanted by the java.time classes.
To specify a moment on the timeline, include the time zone to give context to your date-and-time.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime start = ZonedDateTime.of( 2015 , Month.FEBRUARY , 18 , 23 , 0 , 0 , 0 , z );
Track your reserved number of hours as a Duration.
Duration duration = Duration.ofHours( 3 );
The ZonedDateTime class knows how to do math with a Duration.
ZonedDateTime zdtStop = zdtStart.plus( duration );
You say you have two data-entry fields for hours and minutes. Convert each text entry to a number. The Long class parses a string to a long primitive.
From those numbers get a Duration of hours and minutes.
Duration duration = Duration.ofHours( Long.parseLong( hoursEntry ) )
.plusMinutes( Long.parseLong( minutesEntry ) ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Julian date to regular date conversion

How do i convert a julian date 2456606 which stands for Nov 18 2013 to the string format 18/11/2013 using java APIs? I tried executing the below code but it is not giving me the right answer. Any corrections to the below code are welcome
String j = "2456606";
Date date = new SimpleDateFormat("yyyyD").parse(j);
String g = new SimpleDateFormat("dd.MM.yyyy").format(date);
System.out.println(g);
tl;dr
LocalDate.MIN.with (
java.time.temporal.JulianFields.MODIFIED_JULIAN_DAY ,
2_456_606L
)
2013-11-09
Other direction, from modern date to Julian Day.
LocalDate.of( 2013 , 11 , 9 )
.getLong ( java.time.temporal.JulianFields.JULIAN_DAY )
2456606
Details
Firstly, your comment:
the julian date to be 2456606 for nov 18 in the converter link mentioned below aa.usno.navy.mil/data/docs/JulianDate.php
…is incorrect. That web site returns November 9, 2013 for 2456606.
Your Navy web site defines Julian Date as a count of days since January 1, 4713 BC mapped to “Universal Time”. I assume they mean UTC and the modern ISO 8601 calendar system. See Wikipedia.
The java.time classes built into Java make this easy.
long input = 2_456_606L;
LocalDate ld = LocalDate.MIN.with ( java.time.temporal.JulianFields.JULIAN_DAY , input );
Dump to console.
System.out.println ( "input: " + input + " is: " + ld );
input: 2456606 is: 2013-11-09
For more discussion, see my Answer on a duplicate Question.
Going the other direction, converting a modern date to a Julian Day.
long output = ld.getLong ( java.time.temporal.JulianFields.JULIAN_DAY );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
The Julian date for Nov 18 2013 is "2013322". The number you used, "2456606", would be the 606th day of 2456, which is Aug 28, 2457.
You might also have intended to use a different date format than "yyyyD" for your input. See http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html for information on possible codes.
Edit
The value that you used for the Julian date is the number of days since January 1, 4713 BCE. To get the Julian date using that system, you'll need to do something like the following:
String j = "2456606";
int day = Integer.parseInt(j) - x; // x == Jan 1, 1970 on the Gregorian
j = Integer.toString(day);
Date date = new SimpleDateFormat("D").parse(j);
String g = new SimpleDateFormat("dd.MM.yyyy").format(date);
System.out.println(g);
Where x is the Julian day corresponding to Jan 1, 1970 on the Gregorian calendar, i.e., the number of days elapsed between January 1, 4713 BCE and Jan 1, 1970.
If you have 7 digit julian date then you can use the following to convert it to Gergorian date.
The longJuliandate is your input and it'd return a String, which you can format for Date. You'd need to use "yyDDD" if you've 5 digit Julian date.
DateFormat dt = new SimpleDateFormat("yyyyDDD");
try
{
Date date = dt.parse(longJulianDate); //2018038
String str = new SimpleDateFormat("yyyyMMdd").format(date);
} catch (ParseException e) {}

Categories

Resources