This question already has answers here:
I am trying to figure out the difference in days between two dates manually
(2 answers)
Closed 25 days ago.
The Question:
"create a method called compare, which takes a parameter of type Date and calculates the number of days between the date of the current object and the input object."
public class Date {
int year;
int month;
int day;
void print() {
System.out.printf("Date: %d/%d/%d", this.month, this.day, this.year);
}
void addDays(int n) {
int[] month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int i = this.month - 1;
int day = this.day + n;
while (day > month[i]) {
day -= month[i];
if (this.month == 12) {
this.year++;
this.month = 0;
i = -1;
}
this.month++;
i++;
}
this.day = 0;
this.day += day;
}
int compare(Date d1) {
return 0;
}
}
This is what I currently have and I was wondering how would I implement this method I've tried messing around with the my method add days but I couldn't quite figure it out.
Again, I've tried messing around with addDays and adding parameter so that the method the object is calling must always be older than the one being compared but I get quite lost. Any advice would help.
you can refer to this post for complete explanation.
when you have two date objects simply subtract them:
long diff = date1.getTime() - date2.getTime();
and count the days:
TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
Related
I would like to ask someone if he/she can help me find the bug where I lose 2 solutions in this problem. My code isn't very pretty and readable but I think it is simple enough to understand logic here. I am sitting on this one for hour and even made up different solution which works but can't find problem in this one.
private static int _year = 1900;
private static int[] _months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private static int _month = 0;
private static int _day = 7; //we start from Sunday
private static int counter = 0;
public static void main(String[] args) {
while(_year !=1901)
nextSunday(_day, _month, _year);
while(true) {
if(_year == 2000 && _month == 11 && _day > 31) break;
nextSunday(_day, _month, _year);
}
System.out.println(counter);
}
private static void nextSunday(int day, int month, int year) {
if(isSundayFirst(_day)) counter++;
if(year == 2000 && month == 11 && day + 7 > _months[month]) { //to break loop
_day = day + 7;
} else if(month == 11 && day + 7 > _months[month]) { // new year, end of month
_day = day + 7 - _months[month];
_month = 0;
_year++;
} else if(month == 1 && isLeapYear(year) && day + 7 > 29) { // leap year end of february
_day = day + 7 - 29;
_month++;
} else if(month == 1 && !isLeapYear(year) && day + 7 > _months[month]) { // not leap year end of february
_day = day + 7 - _months[month];
_month++;
} else if(day + 7 > _months[month]) { // end of month
_day = day + 7 - _months[month];
_month++;
} else { // next in same month
_day = day + 7;
}
}
private static boolean isSundayFirst(int day) {
return day == 1;
}
private static boolean isLeapYear(int year) {
if(isCentury(year)) {
if(year % 400 == 0) return true;
} else {
return year % 4 == 0;
}
return false;
}
private static boolean isCentury(int year) {
return year % 100 == 0;
}
I got 169 such Sundays. I should get 2 more.
Here is the problem:
You are given the following information, but you may prefer to do some
research for yourself.
1 Jan 1900 was a Monday.
Thirty days has September,
April, June and November.
All the rest have thirty-one,
Saving February alone,
Which has twenty-eight, rain or shine.
And on leap years, twenty-nine.
A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
How many Sundays fell on the first of the month during the twentieth
century (1 Jan 1901 to 31 Dec 2000)?
I will appreciate any effort. Thank you.
PS I know this _name style isn't Java like but I was writing it fast without intention of posting it anywhere tbh.
There are two issues with your code, one that causes you to over count by 2 and another that causes you to undercount by 4.
Issue #1 The problem to tells you to start counting in 1901, but you start counting in 1900.
Change
if(isSundayFirst(_day)) counter++;
to
if(isSundayFirst(_day) && _year >= 1901) counter++;
to fix this.
Issue #2 The issue lies in this condition:
else if(day + 7 > _months[month]) { // end of month
_day = day + 7 - _months[month];
_month++;
}
You've handled the case where it is February in the previous two conditions, so you need to check to make sure it is not February here. Changing the condition to
else if(month != 1 && day + 7 > _months[month])
will fix your issue.
Sidenote: The structure of your nextSunday method made it quite difficult to decipher, so here is my effort to simplify it (you will now break when _year > 2000):
private static void nextSunday(int day, int month, int year) {
int febNum = isLeapYear(_year) ? 29 : 28;
int dayCount = (month == 1) ? febNum : _months[_month]; //days in current month
_day += 7;
if (_day > dayCount) { //new month
_month++;
_day -= dayCount;
}
if (_month == 12) { //new year
_month = 0;
_year++;
}
}
I would like to calculate exact age in days considering leap years. I researched on the web, found some tutorials, but with leap years that exactly calculates difference of dates in days seems to be the one in [1]: https://answers.yahoo.com/question/index?qid=20110629162003AAof4mT this link, which is "best answer" . I analyzed code but have two questions:
1) Why it writes "days = days + leapYears" below "Calculate days lives" section and
2) Finally, how can I input birthday date with day,month and year and current day,month,year and find difference of these two dates in days within this code in the main method? I really appreciate your help. Thanks in advance !
PS: For convenience, I have included the code from the link I showed above:
public class Days {
static int leapYear(int year) {
int leap;
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
leap = 1;
}
else {
leap = 0;
}
return leap;
}
static int daysBefore(int month, int day, int year){
int days = 0;
int monthDays[] = new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (leapYear(year) == 1){
monthDays[1] = 29;
}
for (int b = 0; b < month - 1; b++){
days = days + monthDays[b];
}
days = days + day;
return days;
}
public static void main(String[] args) {
//Birth date
int birthMonth = 0;
int birthDay = 0;
int birthYear = 0;
//Due date
int dueMonth = 0;
int dueDay = 0;
int dueYear = 0;
//(1) Calculate years lived
int yearsLived = dueYear - birthYear + 1;
//(2) Calculate leap years
int leapYears = 0;
for (int year = birthYear; year < dueYear+1; year++)
{
leapYears = leapYears + leapYear(year);
}
//(3) Calculate the number of days in your birth year before birth
int daysBeforeBirth = daysBefore(birthMonth, birthDay, birthYear);
//(4) Calculate the number of days remaining in the current year after the due date
int daysRemaining = 365 - daysBefore(dueMonth, dueDay, dueYear);
//Calculate days lived
int days = 0;
days = days + (365 * yearsLived);
days = days + leapYears;
days = days - daysBeforeBirth;
days = days - daysRemaining;
}
}
The correct way to do this is with the Period and LocalDate classes in the java.time package. However, it seems that you're trying to reinvent the calculation for yourself.
The way that I would recommend doing this is to write a class that lets you calculate a "day number" for a given date - that is, the number of days between the specified date, and some arbitrary date in the past. Then when you want to find the number of days between two specified dates, you can just use calculate the "day number" for both dates, and subtract them.
I have done that here, for a purely Gregorian calendar. This class is no good before the Gregorian cutover - I haven't tried to build a historically accurate Julian/Gregorian hybrid calendar, such as the JDK provides. And the arbitrary date in the past that it calculates day numbers from is 31 December, 2BC. This date, of course, isn't really part of the Gregorian calendar; but for our purposes here, it doesn't matter.
Since you're unlikely to encounter any dates before the Gregorian cutover, this class should be more than adequate for your purposes. I still recommend using the Period and LocalDate classes instead of this one, for production code. This is just here so you can see how to do the calculations.
public class GregorianDate {
private final int day;
private final int month;
private final int year;
private static final int[] DAYS_PER_MONTH = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public GregorianDate(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
public boolean isValid() {
return month >= 1 && month <= 12 && day >= 1 && day <= daysThisMonth();
}
public static int daysBetween(GregorianDate from, GregorianDate to) {
return to.dayNumber() - from.dayNumber();
}
public static int daysBetween(int fromDay, int fromMonth, int fromYear, int toDay, int toMonth, int toYear) {
return daysBetween(new GregorianDate(fromDay, fromMonth, fromYear), new GregorianDate(toDay, toMonth, toYear));
}
private int daysThisMonth() {
return (isLeapYear() && month == 2) ? 29 : DAYS_PER_MONTH[month];
}
private int dayNumber() {
return year * 365 + leapYearsBefore() + daysInMonthsBefore() + day;
}
private boolean isLeapYear() {
return ( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0;
}
private int leapYearsBefore() {
return year / 4 - year / 100 + year / 400;
}
private int daysInMonthsBefore() {
switch(month) {
case 1:
return 0;
case 2:
return 31;
default:
// Start with the number in January and February combined
int toReturn = isLeapYear() ? 60 : 59;
for (int monthToConsider = 3; monthToConsider < month; monthToConsider++) {
toReturn += DAYS_PER_MONTH[monthToConsider];
}
return toReturn;
}
}
}
To answer question 1.
every leapyear you add 1 day to the year. The writer uses this knowledge by first calculating how many days have been lived if all years were normal:
days = days + (365 * yearsLived);
and then adds the number of leapyears(remember 1 leapyear = 1 extra day).
For the second question:
the code seeks the difference between birthDate(read: startDate) and dueDate(read endDate). So to calculate the difference between start and end you have to give these integers the the date input and the code will do the rest.
tl;dr
long ageInDays =
ChronoUnit.DAYS.between(
LocalDate.of( 1960 , 1 , 2 ) ,
LocalDate.now( ZoneId.of( "America/Montreal" ) )
);
Using java.time
If you are exploring the algorithm, see the apparently correct Answer by David Wallace.
If you are doing this for productive work, then do not roll your own date-time classes. Avoid the old date-time classes (.Date, .Calendar, etc.) and use the java.time classes.
The ChronoUnit enum has a surprising amount of utility including calculating elapsed time. Pass a couple of Temporal objects, in our case LocalDate objects.
LocalDate start = LocalDate.of( 1960 , 1 , 2 ) ;
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;
long ageInDays = ChronoUnit.DAYS.between( start , today ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
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.
I am using System.currentTimeMillis() to get number of milliseconds since 1970, I am able to get current Hour, Minute, seconds and year. For example I am getting Year using following formula and it returns 2015:
((((currTimeInMilliSec / 1000) / 3600) / 24) / 365) + 1970
But how can I calculate Month from milliseconds keeping in considering Leap Year and different number of days in different months like 28,29,30,31.
Note: For some reason, I need to use only currentTimeMillis function to calculate and I don't want to use other functions or external libraries. Also I have gone through related posts but didn't find exact answer.
Use GregorianCalendar.
GregorianCalendar c = new GregorianCalendar();
c.setTimeInMillis(1l);
int month = c.get(Calendar.MONTH);
This returns 0, that is January. Imagine an array with the 12 months of the year.
Yes, this is possible.
There are astronomical algorithms that enable the numerical translation between a Julian Day Number and a date-time stamp. The algorithm with which I am familiar was published by J. Meeus in his Astronomical Algorithms, 2nd Ed. This algorithm will convert a Julian Day Number to a vector of integers representing the corresponding:
YEAR
MONTH_IN_YEAR (1-12)
DAY_IN_MONTH (1-28,29,30,31 as appropriate)
HOUR_IN_DAY (0-23)
MINUTE_IN_HOUR (0-59)
SECOND_IN_MINUTE (0-59)
MILLISECOND_IN_SECOND (0-999)
Because both POSIX time and Julian Day Numbers are date serials (counts of consecutive time units) they are trivial to interconvert. Thus, the 1st step for using this algorithm would be to convert POSIX time (millis since midnight Jan 1, 1970) to a Julian Day Number (count of days since November 24, 4714 BC, in the proleptic Gregorian calendar). This is trivial to do since you simply convert from millis to days and adjust the epoch.
Here are the constants:
/** Accessor index for year field from a date/time vector of ints. */
public static final int YEAR = 0;
/** Accessor index for month-in-year field from a date/time vector of ints */
public static final int MONTH = 1;
/** Accessor index for day-in-month field from a date/time vector of ints */
public static final int DAY = 2;
/** Accessor index for hour-in-day field from a date/time vector of ints */
public static final int HOURS = 3;
/** Accessor index for minute-in-hour field from a date/time vector of ints */
public static final int MINUTES = 4;
/** Accessor index for second-in-minute field from a date/time vector of ints */
public static final int SECONDS = 5;
/** Accessor index for millis-in-second field from a date/time vector of ints */
public static final int MILLIS = 6;
/** The POSIX Epoch represented as a modified Julian Day number */
public static final double POSIX_EPOCH_AS_MJD = 40587.0d;
And here is the method for the algorithm that converts a Julian Day Number (supplied as a double) to a vector of integers. In the code below, you can substitute the trunc() function with Math.floor() and retain the correct behavior:
public static int[] toVectorFromDayNumber(double julianDay) {
int[] ymd_hmsm = {YEAR, MONTH, DAY, HOURS, MINUTES, SECONDS, MILLIS};
int a, b, c, d, e, z;
double f, x;
double jd = julianDay + 0.5;
z = (int) trunc(jd);
f = (jd - z) + (0.5 / (86400.0 * 1000.0));
if (z >= 2299161) {
int alpha = (int) trunc((z - 1867216.25) / 36524.25);
a = z + 1 + alpha - (alpha / 4);
} else {
a = z;
}
b = a + 1524;
c = (int) trunc((b - 122.1) / 365.25);
d = (int) trunc(365.25 * c);
e = (int) trunc((b - d) / 30.6001);
ymd_hmsm[DAY] = b - d - (int) trunc(30.6001 * e);
ymd_hmsm[MONTH] = (e < 14)
? (e - 1)
: (e - 13);
ymd_hmsm[YEAR] = (ymd_hmsm[MONTH] > 2)
? (c - 4716)
: (c - 4715);
for (int i = HOURS; i <= MILLIS; i++) {
switch (i) {
case HOURS:
f = f * 24.0;
break;
case MINUTES: case SECONDS:
f = f * 60.0;
break;
case MILLIS:
f = f * 1000.0;
break;
}
x = trunc(f);
ymd_hmsm[i] = (int) x;
f = f - x;
}
return ymd_hmsm;
}
For example, if the function is called with the Julian Day Number 2457272.5, it would return the following vector of integers representing midnight, Sept 7, 2015 (Labor Day) in UTC:
[ 2015, 9, 7, 0, 0, 0, 0 ]
Edit: A remarkable thing about the Meeus algorithm is that it correctly accounts for both Leap Years and century days (including the century day exception). It uses only integer and floating point arithmetic and is very likely to be more performant than solutions which require object instantiations from the Java Calendar or Date-Time APIs.
My variant:
public class Main {
public static class MyDate {
int month;
int day;
public MyDate(int month, int day) {
this.month = month;
this.day = day;
}
}
public static final int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public static void main(String[] args) {
long millis = System.currentTimeMillis();
long days = millis / 86400000;
long millisToday = millis % 86400000;
int yearsPassedApprox = (int) days / 365;
int daysPassedThisYear = (int) (days - (yearsPassedApprox * 365 + leapYearsCount(yearsPassedApprox)));
int year = yearsPassedApprox + 1970;
MyDate myDate = getMonthAndDay(year, daysPassedThisYear);
int hours = (int) (millisToday / 3600000);
int minutes = (int) ((millisToday % 3600000) / 60000);
int seconds = (int) ((millisToday % 60000) / 1000);
System.out.println("Year: " + year);
System.out.println("Month: " + myDate.month);
System.out.println("Day: " + myDate.day);
System.out.println("Hour: " + hours);
System.out.println("Minutes: " + minutes);
System.out.println("Seconds: " + seconds);
}
public static MyDate getMonthAndDay(int year, int daysPassedThisYear) {
int i;
int daysLeft = daysPassedThisYear;
boolean leapYear = isLeapYear(year);
for (i = 0; i < daysInMonth.length; i++) {
int days = daysInMonth[i];
if (leapYear && i == 1) {
days++;
}
if (days <= daysLeft) {
daysLeft -= days;
} else {
break;
}
}
return new MyDate(i + 1, daysLeft + 1);
}
public static int leapYearsCount(long yearsPassed) {
int count = 0;
for (int i = 1970; i < 1970 + yearsPassed ; i++) {
if (isLeapYear(i)) {
count++;
}
}
return count;
}
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && !(year % 100 == 0)) || year % 400 == 0;
}
}
I need to claculate the number of days between two dates without using any date or calendar classes provided by any library.
Here's my idea:
numberOfDays = Math.abs((toYear - fromYear) * 365);
numberOfDays = numberOfDays + Math.abs((toMonth - fromMonth) * 12);
numberOfDays = numberOfDays + Math.abs((toDay - fromDay));
Thoughts?
How many days between the start date and the end of the month?
How many days in each full month until the end of the year?
How many days in each full year until the year of the end date (counting leap years)?
How many days in each full month until the last month?
How many days from the start of the last month until the end date?
Some of these numbers may be zero.
In Java 8 you can do the following:
long days = ChronoUnit.DAYS.between(LocalDate.of(2014, Month.MARCH, 01), LocalDate.of(2014, Month.FEBRUARY, 15));
Would something like this do?
//get 2 random dates
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = new Date();
Date date2 = sdf.parse("2014-9-12");
final long msInADay = 24*60*60*1000; //turn a day to ms
//divide time difference by the ms of a day
int difference = (int)((date2.getTime() - date1.getTime()) / msInADay);
System.out.println(Math.abs(difference));//Math.abs so you can subtract dates in any order.
EDIT after updating your question:
You can do this:
static int calcDayDiff(int startY, int startM, int startD, int endY, int endM, int endD){
int result = (startY - endY) * 365;
result += (startM - endM) * 31;
result += (startD - endD);
return Math.abs(result);
}
Testing with: System.out.println(calcDayDiff(2014,9,13,2013,8,12)); will print 397
Note though that this is not a very good solution since not every month contains 31 days and not every year 365. You can fix the month day difference by adding some simple logic inside the method to not always multiply by 31. Since it's an assignment i guess you will be ok to consider every year having 365 days.
public class test {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(2014, 8, 1, 0, 0, 0);
Date s = cal.getTime();
Date e = new Date();
System.out.println(days(s,e));
}
public static int days(Date start, Date end){
double aTms = Math.floor(start.getTime() - end.getTime());
return (int) (aTms/(24*60*+60*1000));
}
}
It's my first question on this site, but I always found this site really useful.
What I mean with my question is:
you ask the person to give a date (eg. Fill in a date [dd-mm-yyyy]:
16-10-2013)
you than have to ask an interval between 2
years (eg. Give an interval [yyyy-yyyy]:1800-2000)
When the program runs, it has to show what day of the week the given date is. In this case it was a Wednesday. Than the program has to look in which year, in between the interval, the date 16 October also fell on a Wednesday.
So in the end it has to look something like this:
Fill in a date: [dd-mm-yyyy]: 16-10-2013
Give an interval [yyyy-yyyy]: 1900-2000
16 October was a wednesday in the following years:
1905 1911 1916 1922 1933 1939 1944 1950 1961 1967 1972 1978 1989 1995 2000
The full date is Wednesday 16 October, 2013
The small (or biggest) problem is, I am not allowed to use the DATE.function in java.
If someone can help me with the second part I would be really really happy, cause I have no idea how I am supposed to do this
To find out what day of the week the given date falls, I use the Zeller Congruence
class Day {
Date date; //To grab the month and year form the Date class
//In this class I check whether the giving date is in the correct form
int day;
int year1; //First interval number
int year2; //Second interval number
final static String[] DAYS_OF_WEEK = {
"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday"
};
public void dayWeekInterval{
int interval.year1;
int interval.year2;
for(int i = year1; year1 =< year2; year1++) {
//check if the day of the week in the giving year, is the same as the
//original year.
}
}
public void dayOfTheWeek {
int m = date.getMonth();
int y = date.getYear();
if (m < 3) {
m += 12;
y -= 1;
}
int k = y % 100;
int j = y / 100;
int day = ((q + (((m + 1) * 26) / 10) + k + (k / 4) + (j / 4)) +
(5 * j)) % 7;
return day;
}
public string ToString(){
return "" + DAYS_OF_WEEK[day] + day;
}
Hey, I changed my code a bit, but I don't know how to knot the tie. Also I forgot to mention, I am not allowed to use the Date and Calendar function of java... And I pretty much did something wrong with the outlook..
Just a simple formula to find day for given date dd - MM - yyxx is,
( dd + m + xx + (xx/4) + (yy%4) ) % 7
% is modulus operator which is remainder in general
The answer got above will tell you day of week i.e. 0 : Mon 1: Tue .... 6 for Sun
Here,
dd - Date given
m - month value which is shown down in list calculated with MM value
yy - first two digits of supplied year
xx - last two digits of year
Now, m value calculation is,
0 for Jan and Oct
1 for May
2 for August
3 for Feb, March and Nov
4 for June
5 for Sept and Dec
6 for July and April
Remember if month supplied is Jan or Feb and the year supplied is leap then subtract 1 from m value in above table i.e. -1 for Jan and 2 for Feb
Leap Year Calculation is
if (yyyy % 4 == 0)
{
if( yyyy % 100 == 0)
{
return (yyyy % 400) == 0;
}
else
return true;
}
I hope rest of programming you can do.
This will help you find the day of week for supplied date and now you just need to add loop for all the years.
You cannot use Datebut can you use Calendar? Then this would be your code:
Calendar c = Calendar.getInstance();
c.set(2013, 9, 16); // month starts at zero
System.out.printf("Original date is: %tc\n", c);
int weekday = c.get(Calendar.DAY_OF_WEEK);
System.out.printf("Weekday of original date is [by number] %d\n", weekday);
for(int year = 1800; year < 2000; year++) {
c.set(Calendar.YEAR, year);
if(weekday == c.get(Calendar.DAY_OF_WEEK))
System.out.printf("%tc was same weekday!\n", c);
}