This is my first month on java. I got a logical error that updates the this value each time I call the method.How can I fix this and make static so each time the original data and time is not change.
result:
testing 7 arg constructor with initial date: [2-28-2015],[12:30:30:0]
Increasing day by 366 [2-29-2016],[12:30:30:0]
Increasing month by 12 [2-28-2017],[12:30:30:0]<---- should be 2016
Increasing year by 2 [2-28-2019],[12:30:30:0]<-------should be 2017
Initial date is [2-28-2016],[12:30:30:0]
Increasing day by 365 [2-27-2017],[12:30:30:0]
Increasing month by 11 [1-27-2018],[12:30:30:0]
Increasing year by 30 [1-27-2048],[12:30:30:0]
here is my code:
public class DateTime implements DateConstants {
private Date date; // from Date Class
private Time time; // from Time class
}
public DateTime addMonths(int mo)
{
this.date.addMonths(mo);
return this;
}
public static void main(String[] myArgs) {
dateTime1 = new DateTime(2,28,2015,12,30,30,0);
System.out.println("testing 7 arg constructor with initial date: "+dateTime1);
System.out.println("Increasing day by 366 "+dateTime1.addDays(366));
System.out.println("Increasing month by 12 "+dateTime1.addMonths(12));
System.out.println("Increasing year by 2 "+dateTime1.addYears(2));
}
If I'm understanding you correctly, you want your additions to add to the base value that the object was created with. Right now, you have one object that is maintaining its state through execution, so when you say dateTime1.addDays(366), it's modifying that object permanently.
You'll have to either put in functionality to hold onto the values passed into the constructor to "reset" to, or re-instantiate the DateTime object after every modification.
As others have said, there is a meaning to the word static, and this is not appropriate. Please change your title.
if i understand correctly your question, I think you can try this
public class DateTime implements DateConstants {
private Date date; // from Date Class
private Time time; // from Time class
}
public DateTime addMonths(int mo)
{
DateTime temp=this.clone();
return temp.date.addMonths(mo);
}
public static void main(String[] myArgs) {
dateTime1 = new DateTime(2,28,2015,12,30,30,0);
System.out.println("testing 7 arg constructor with initial date: "+dateTime1);
System.out.println("Increasing day by 366 "+dateTime1.addDays(366));
System.out.println("Increasing month by 12 "+dateTime1.addMonths(12));
System.out.println("Increasing year by 2 "+dateTime1.addYears(2));
}
if you re-create the object before each system.out, you'll get the result you want.
it seems that your object is being reused
The declaration of "dateTime1" is missing from your code, and then we assume it´s a class attribute, but you should show in your question where it is declared.
Related
Suppose two people run the same code and the first one creates a certificate with createDate and expireDate and a file is valid if
createDate < currentTimeOfTheUserComputer < expireDate .
Now if the first person sends this certificate(suppose for him it is valid) to someone else who is 8 hours behind around the world ,for the second person it will be invalid.In such a scenario how is this problem resolved or is there a policy how it should be if we want the second person to be able to use it without waiting 8 hours?
RFC 5280, which handles X.509 certificates specifies two methods to encode validity times in certificates:
UTCTime
GeneralizedTime
Both rely on the GMT zone as reference. If both implementations use the correct time zone for generation and checking, your scenario should not present a problem.
See RFC 5280 on validity
EDIT: Sorry, I didn't realize that Date always uses UTC Time. So any time you want to get the date, you access it like this:
import java.util.Date;
public class CurrentDateTime {
public static String getCurrDateTime() {
Date date = new Date();
return date;
}
}
public class DateCertificate {
public static void createCertificate() {
Date createDate = CurrentDateTime.getCurrDateTime();
/* Save createDate to file or something */
}
public static boolean certificateValid() {
Date currentDate = CurrentDateTime.getCurrDateTime();
/* Get createDate and expireDate from file or something */
return currentDate.after(createDate) && currentDate.before(expireDate);
}
}
You can use getCurrDateTime() and some other Date methods to get the createDate and expireDate and save them to a file or however you want to store them, then use the certificateValid() method to check if the currentDate is between the two.
Thanks Jim for pointing out my mistake.
Note: This could be easily spoofed/tricked because it is dependent on the time reading from the client machine that is given to the JVM. So do not use this for free trial validation or the like.
I was doing the time comparison project, and i used a really dumb way to do it. Please see the code below:
In the function called getInDays, I have calculated how many days per year, and set the days. However, in the next function called getInHours, days cannot be used. Can somebody help me?
Thank you so much!
PS: I have deleted all the other functions in order to make this code easy to see.
package datetimeexample;
public class DateTime {
private int month;
private int day;
private int year;
private Time time;
public void getInDays()
{
int days = year * 365 + month * 31 + day;
}
public void getInHours()
{
int totalHours = days*12 + time.getHour();
}
}
days is a declared within the getInDays() method. The scope of days is local to the getInDays() methods.It cannot be accessed from outside that method.
You have 2 options.
Declare days outside the getInDays() methods and make its scope instance level.
Instead of using days in getInHours() call getInDays() directly. (Provided you change the return type of the method.
Check this link for more info
I have a parametrized method:
private static Date getTimeFor(int hour, int minute, int second, int nanoSecond, String zoneId) {
ZonedDateTime time = ZonedDateTime.now()
.withZoneSameLocal(ZoneId.of(zoneId))
.withHour(hour)
.withMinute(minute)
.withSecond(second)
.withNano(nanoSecond);
return Date.from(time.toInstant());
}
Followed by:
private Date getRomeStartTime(){
return getTimeFor(8,30,0,0,"Europe/Rome");
}
private Date getParisStartTime(){
return getTimeFor(9,30,0,0,"Europe/Paris");
}
private Date getLondonStartTime(){
return getTimeFor(9,00,0,0,"Europe/London");
}
This can get out of hand quickly as more cities are added. I'm aiming to only make public/expose the below method and delegate the construction of StartTimes elsewhere:
public Date getEffectiveTimeFor(String zoneId){
// Delegate construction as per zoneId elsewhere
// dont want to use a long-winded if-else statement
}
I cant use the strategy pattern as I should not pass an object, but only a string.
What is the best approach here?
(p.s. I have to return the old Date, this is beyond the question )
You can simply use a Map<String, LocalTime> to store the start time for each zone ID. Then get the start time from this map in your method and create the Date from there.
This question already has answers here:
Unit testing time-based logic in Java
(3 answers)
Handling unit tests with a condition on the current time
(6 answers)
Setting time and date in JUnit test fixture
(4 answers)
Writing and testing convenience methods using Java 8 Date/Time classes
(1 answer)
Closed 3 years ago.
So I have a class that has a method "getDaysUntil(Date date)" which returns the number of days until the date given as parameter. I mention that I cannot change the class below:
public class A {
public int getDaysUntil(Date givenDate) {
... // code
Date currentDate = new Date() //it creates a date object holding the current day
...// code that calculates the nr of days between currentDate and givenDate.
}
I have to do some unit testing and you might see the problem, it creates currentDate inside the method and the returned value will be different from day to day. I have tried to mock a Date object or "override" System.currentTimeMillis() with PowerMock but to no avail.
Is there any way to properly test these kind of methods?
Use a class that serves as a DateFactory, which is called to construct Date objects in your application code.
Then just mock the method of that DateFactory in your unit test. That way you can make it return whatever date you want as a virtual "current date"
One solution where System.currentTimeMillis() is mocked is as follows, using the JMockit library (it should be possible with PowerMock too):
#Test #SuppressWarnings("deprecation")
public void daysUntilCurrentDate() {
final long fakeCurrentDateInMillis = new Date(2017, 2, 1).getTime();
new MockUp<System>() {
#Mock long currentTimeMillis() { return fakeCurrentDateInMillis; }
};
A tested = new A();
int daysSinceJan30 = tested.getDaysUntil(new Date(2017, 1, 30));
assertEquals(2, daysSinceJan3O);
}
I understand that you cannot change the method that you need to test. Unfortunately this also means that you are stuck with the old and often not very programmer-friendly Date class (I am assuming java.util.Date).
Edit: The no-arg Date constructor that your method uses in turn uses System.currentTimeMillis(), a static native method. I didn’t know there were tools that could mock contructors and static native methods, but was informed by comment and answer by #Rogério, the developer of JMockit, that such mocking tools exist.
In any case, there is an alternative: you calculate some number of days from today, pass the resulting Date to the method and check that you get the number back you used in your calculation. This will work on any day and requires no mocking/stubbing.
In the code below I am assuming that the getDaysUntil method should discard the hours and minutes and just look at the date in the computer’s time zone. If the real requirements differ, you can probably make the appropriate adjustments to my code.
We want to take into account that the method may run over midnight. If so, I consider the result undefined since we do not know whether the Date object was constructed before or after midnight. In this case I simply try again, assuming the test will finish before the next midnight.
#Test
public void testGetDaysUntil() {
A instanceUnderTest = new A();
for (int daysToTest = 0; daysToTest <= 400; daysToTest++) {
LocalDate today;
int result;
do {
today = LocalDate.now(); // do this in each iteration in case day changes underway
LocalDate targetDate = today.plusDays(daysToTest);
Date midnightAtStartOfDay = Date.from(targetDate.atStartOfDay(ZoneId.systemDefault())
.toInstant());
result = instanceUnderTest.getDaysUntil(midnightAtStartOfDay);
} while (! today.equals(LocalDate.now())); // if we have passed midnight, try again
assertEquals(daysToTest, result);
do {
today = LocalDate.now();
LocalDate targetDate = today.plusDays(daysToTest);
Date nearMidnightAtEndOfDay = Date.from(targetDate.atTime(23, 59, 59, 400_000_000)
.atZone(ZoneId.systemDefault())
.toInstant());
result = instanceUnderTest.getDaysUntil(nearMidnightAtEndOfDay);
} while (! today.equals(LocalDate.now()));
assertEquals(daysToTest, result);
}
}
I have used the Java 8 classes for the date and time calculations. If you cannot use Java 8, Calendar and/or GregorianCalendar can be used, they may be just a little more cumbersome for this job, but at least can be converted to Date easily.
I got the following in the body of the code:
public String getStartDate() {
return (new SimpleDateFormat("dd/MM/yyyy").format(startDate));
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
and startDate is initiated as Date startDate;
When I use the set startdate method, I am setting the value of this instance to the value of the object retrieved from database..
setStartDate(rsvIns.startDate);
Now the problem is here when I try to see if the startDate is equal to TodayDate,
Date todayDate = new Date();
if(startDate.equals(todayDate))
{
changeStatus(requestID, "Active");
}else{
//update status if others approved
changeStatus(requestID, "Approved");
}
I whenever it comes to the equals line it throws error and just doesn't execute the if or else part, hence the statement is never executed. Any idea why this could be happening?
Thanks,
I see 2 problems from the code snippets you provided:
Date todayDate = new Date() object contains in information on Hour, Minutes, Seconds and Milliseconds. If you compare it to a date created from a "dd/MM/yyyy" string you will have a problem caused by the time component of the Date object.
getStartDate() returns a String object. If that value is assigned to the startDate variable from the if statement, then on equals() call with a Date object parameter value the result will be false regardless of the startDate and parameter value, because the classes do not match.
If you get into situations like this and you do not see the answer, copy the code into a small program and debug trace it, look at the values of the objects. Trace into java code.
I have seen many times java developers with years of experience trip on the time component of Date object. They even clear the Hour, Minutes and Seconds and forget about the Milliseconds component.