I'm writing a Java program that automatically generates a certain amount of "units" for the user to do (Actual purpose not important in this question).
I'm struggling to find a good way to determine how many of these "units" to give the user for the next week.
Intentions of the calculation :
Gives "units" of a specific week
Calculates units for the week based on the actual day of the week (Mon-Fri)
Accounts for all of the units that month (Ex. If it is the last week of the month, give all possible units that entire week)
If estimating, should over-estimate (Due to the program's nature, under-estimating would be far worse.)
Units cannot be decimals (Hence the cast to int)
Variables I have :
The amount of "units" to do that month
I have tried to do this in a few different ways, and so far, the best way I have is this :
public static int getRemainingUnitsThisWeek() {
return (int) Math.round(((double) getUnitsThisMonth() / (((30 - (double) DateTime.now().getDayOfMonth()+1) / 7) < 1 ? 1 :
((30 - (double) DateTime.now().getDayOfMonth()+1) / 7))) / (double)DateTime.now().getDayOfWeek());
}
The problem that I end up (specifically, I'm still not happy with how it does it) with is that in the "units" given on the last week of the month is still divided by the day of the week (Which in turn gives you a much lower number each day - even though the user needs to receive all the "units" by the end of the month).
Any questions you might have, just ask!
PS. The library I am using in the DateTime.now() function is joda-time.
Your description is confusing, so I'm not sure I can answer it directly. Instead, I will answer a different question, which may help:
I have a bunch of units to do, and the rest of the month to do them.
How many should I do today?
I don't know about Joda, but using the standard Date API, you can use this answer to get a Date representing the end of the month, a similar technique to get a Date representing the end of today, and new Date() to get the current time. Then subtract their getTime()s. You can then apportion your units now that you know how many milliseconds to the end of the day and the end of the month.
units_today = total_units_to_do * milliseconds_to_end_of_today /
milliseconds_to_end_of_month;
I don't know java, so I won't attempt to write code, but I suggest you start by calculating daysLeftInMonth and daysLeftInWeek. Once you get those working perfectly, you have two simple cases: either the month will end before the week does, or else it won't.
In the first case the rest of the algorithm is trivial. In the second, calculate how many units there should be per day (rounding up), then multiply by the days left in the week.
Related
If I calculate the difference between 2 LocalDate's in java.time using:
Period p = Period.between(testDate, today);
Then I get an output with the number of years, months, days like:
Days = 9
Months = 6
Years = 18
Does anyone know a clean way to represent that as a decimal type value (ie, above would be something around 18.5...)?
You mentioned in one of your comments that you need quarter year precision if you need the current quarter you can use IsoFields.QUARTER_YEARS:
double yearAndQuarter = testDate.until(today, IsoFields.QUARTER_YEARS) / 4.0;
This way you will actually use the time api, always get the correct result and #Mike won't have to loathe anything.
Please do not do this.
Representing the difference between two dates as a 'number of years' multiplier is problematic because the average length of a year between two dates is dependent on which dates you are comparing. It's easy to get this wrong, and it's much harder to come up with all the test cases necessary to prove you got it right.
Most programmers should never perform date/time calculations manually. You are virtually guaranteed to get it wrong. Seriously, there are so many ways things can go horribly wrong. Only a handful of programmers on the planet fully understand the many subtleties involved. The fact that you are asking this question proves that you are not one of them, and that's okay--neither am I. You, along with the vast majority of us, should rely on a solid Date/Time API like java.util.time.
If you really need a single numeric value, then the safest option I can think of is to use the number of days, because the LocalDate API can calculate that number for you:
long differenceInDays = testDate.until(today, ChronoUnit.DAYS)
Note that this difference is only valid for the two dates used to produce it. The round-trip conversion is straightforward:
LocalDate today = testDate.plus(differenceInDays, ChronoUnit.DAYS)
Do not attempt to manually convert a Period with year, month, and day components into a whole number of days. The correct answer depends on the dates involved, which is why we want to let the LocalDate API calculate it for us.
When precision isn't important
Based on your comments, precision isn't an issue for you, because you only want to display someone's age to the nearest quarter-year or so. You aren't trying to represent an exact difference in time; only an approximate one, with a rather large margin for error. You also don't need to be able to perform any round-trip calculations. This changes things considerably.
An approximation like #VGR's should be more than adequate for these purposes: the 'number of years' should be accurate to within 3 days (< 0.01 years) unless people start living hundreds of thousands of years, in which case you can switch to double ;).
#Oleg's approach also works quite well, and will give you a date difference in whole quarters, which you can divide by 4 to convert to years. This is probably the easiest solution to get right, as you won't need to round or truncate the result. This is, I think, the closest you will get to a direct solution from java.util.time. The Java Time API (and date/time APIs in general) are designed for correctness: they'll give you whole units, but they usually avoid giving you fractional approximations due to the inherent error involved in floating-point types (there are exceptions, like .NET's System.TimeSpan).
However, if your goal is to present someone's age for human users, and you want greater precision than whole years, I think 18 years, 9 months (or an abbreviated form like 18 yr, 9 mo) is a better choice than 18.75 years.
I would avoid using Period, and instead just calculate the difference in days:
float years = testDate1.until(today, ChronoUnit.DAYS) / 365.2425f;
Creating league scheduling software and have a math question that I need a little help wrapping my head around.
Say you have 4 teams(for simplicity) and you check every possible permutation of 1,2,3,4. This permutation is only called the first week which gives you 24 possible permutations.
1,2,3,4 is a permutation and say Week 1 1X4 is a game 2X3 is a game.
Week Two's combination of game is set via round robin so 4,1,2,3 is up next; 4X3 1X2 are the game.
My question is that if week two's combination of games does not work (because of constraints) but instead an order of 3,4,1,2 would work would this ever be checked by performing the permutation on week 1? i.e. week 1 was 1,2,3,4 week 2 was 3,4,1,2
Or would I need to permute week 1 then permute week 2 and so on and so on to actually get every possible schedule. My gut is telling me that I do actually need to permute every week in order to actually get every possible permutation of the schedule.
EDIT:
I'm asking if there were four weeks would my permutations calculator be 24*24*24*24 not just 24.
To answer your question directly, just checking all permutations for week 1 will not necessarily result in all possible permutations being checked. Test with some simple samples and you'll see that fairly quickly
It looks to me as if you need a standard Backtracking algorithm. These are designed for exactly these types of problems with constraints.
The general form would be something like
function permutation
if all current matches satisfy constraints
if any weeks remaining to be allocated
for each possible match for next week
call permutation with that match added
else
accept this solution
The assumption is that there are enough constraints that few permutations will be legal. However if many permutations are legal then the process of accepting the solutions will need to take this into account in how they are processed.
As far as I am concerned this solution may help you.
First you take an input that is week from user.After that you compute permutation of week.
And Finally, multiply with power of week.
public class Schedule {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter week");
int x = scan.nextInt();
int y = (int) Math.pow(permutation(x), x);
System.out.println(y);
}
public static int permutation(int week) {
int y;
if (week == 1) {
return 1;
} else {
y = week * permutation(week - 1);
}
return y;
}
}
Given absolute value of angle between hour and minute hands.
We need to find all valid values of time (in hours and minutes, both non-negative integers) from midnight (inclusive) to noon (not inclusive) which satisfy the given angle.
It is to be noticed that time value is considered valid if the angle between the clock's hands for that value and the angle given has described differ by less than 1/120 degrees.
Also, the movement of the minute hand influences the hour hand. That is, every minute, it moves by 1/60th of the angular distance between two consecutive hour marks.
So how to solve this problem in good way. I wrote down a code with hell lot of if and else. So just wondering if there is clean way of finding all of them.
Example : If A=30 then it can be :
01:00
11:00
I'll try an idea in pseudocode
for minuteHand in [0,59]:
minuteAngle=angle(minuteHand) // gives the angle respect to the 0
hourAngle1 = minuteAngle+A //Should be modified to account for the precision
hourAngle2 = minuteAngle-A
if isValidTime(minuteAngle,hourAngle1): // check if the two hands express a valid time at this angle
found a valid time
if isValidTime(minuteAngle,hourAngle2):
found a valid time
Problem of currently going on competition in Codechef.
https://www.codechef.com/OCT15/problems/TIMEASR
I do not really understand what is your problem. "How to solve this?" is a bit to vague to give a short answer. However, the first thing I would do is to convert all values to the same units. 30 degrees corresponds to 1/12th of the full circle, ie in one minute one hand moves by 6 degrees (1/60 of a full turn) and the other one by 1/2 degree (30 degrees in a full hour). So you are basically trying to solve
abs( (t * 6) - (t*1/2) ) == 30 + n*360
where n = 0,1,2,.... That modulo part makes it a bit tedious to get a direct solution, but you can simply run a loop for any values of t to find the solutions. Hope this helps. If not, maybe you should consider showing some of your code....
This question shouldn't be answered right now as it's from a LOng contest being hosted by codechef. So , this is spoiling the problem for enthusiasts like us who wants to solve this on our own.
Hi all I have a piece of code which looks like this:
public class Test {
public static void main(String args[]) {
long a = System.currentTimeMillis(); // line 1
long b = System.currentTimeMillis(); // line 2
assert b - a >= 0;
long y = System.nanoTime(); // line 5
long z = System.nanoTime(); // line 6
}
}
So IERS stated that the next leap second is to occur immediately after 30th June 2012 11:59.9.
I was wondering if I'm right to say that if line 1 is run at 0.9 seconds after 30th June 2012 11:59.9 turns 1st July 2012 00:00.0,
And line 2 is run at 0.1 second after line 1,
The result of b - a could be negative ? (-900 milliseconds)
If that's the case, is it true that if line 5 is run at 0.9 seconds after 30th June 2012 11:59.9 turns 1st July 2012 00:00.0,
And line 6 is run at 0.1 second after line 5,
The result of z - y could be negative ? (-900,000,000 nanoseconds?)
System.nanoTime should be monotonically increasing -- if you have two calls to it, A and B, and A happens-before B, then A <= B. But in practice, you can actually observe nanoTime going "backwards."
nanoTime is determined by an internal counter on the CPU whose starting time is essentially arbitrary (which is why it can't be used to determine wall clock time). This can cause a problem in multi-core environment, since one core's internal timer may have a different starting point than another's. Hotspot tries to compensate for this, but it doesn't always succeed, so you can in fact see nanoTime ticking backwards in some situations.
There was a recent discussion about this on the concurrency-interest mailing list. See in particular this email which links to this bug report, and this email which talks about the workaround (which doesn't seem to work, though I'm not sure why). The bug report has a fair amount of detail.
Am I right to say that if line 1 is run at 0.9 seconds after 30th June 2012 11:59.9 turns 1st July 2012 00:00.0,
If the clock is not adjusted, 0.9 seconds after 30th June 2012 11:59.9 is 1st July 2012 00:00.8
The result of b - a would be negative ?
The currentTimeMillis() is the time in milli-seconds since 1970. It doesn't reset at the start of the day. Or any time in your life time.
The result of z - y would be negative ?
nanoTime() is not the time since the start of the day either. On many JVMs/OSes its the number of nano-seconds since the CPU was last reset.
Not all OSes provide the same resolution. e.g. RHEL/Centos 5.x give only micro-second resolution. This means you can have many calls in a row give the same value (to the micro-second)
long a = System.currentTimeMillis(); // line 1
long b = System.currentTimeMillis(); // line 2
assert b - a >= 0;
This will go backwards whenever the time is corrected by turning it backwards. e.g. via NTP.
long y = System.nanoTime(); // line 5
long z = System.nanoTime(); // line 6
This will go backwards on systems with more than one socket which do no correct for the difference in the Time Stamp Counter in different sockets. e.g. if you are on Windows XP and have two Sockets you can see the difference jump by 4,000,000 forward or backward as it switch the thread between sockets.
No, you are wrong. Because this is not millisecond part of current time, but total milliseconds passed from year 1970.
They could be the same, but later is not less than earlier. However, if a NTP daemon doing its job it could happen, if at some moment the system clock has been adjusted.
The nanoTime is more reliable way, since it doesn't depend on the system clock and should not be changed by clock adjustments.
-System.nanoTime() + System.nanoTime() guaranteed to be >= 0?
Yes. It's a timer, not any absolute time, and according to its docs, it Returns the current value of the most precise available system timer, in nanoseconds. The value returned represents nanoseconds since some fixed but arbitrary time. Time since some fixed time doesn't go backwards (although after 292 years the difference will overflow, but that's hardly a practical issue. Also, as Peter Lawrey pointed out, Windows XP has a bug that breaks nanotime's guarantees).
System.currentTimeMillis() is completely different. It returns absolute time (milliseconds since 1970) which is got from the computer's clock, which could be adjusted anytime.
My reading of the wiki page is same as yours: currentTimeMillis() can go backwards due to leap second.
(Why did they bring this fine astronomical problem into civil time? No civilian cares if solar noon is off by a few seconds; actually nobody uses local time to begin with; people in the same time zone can observer solar noon differ by 1 hour. and in a big country with no time zone, the difference can be hours.)
I use for example this code to check if the user can do some action. So the user can only do one action each 5 seconds.
if((System.currentTimeMillis() - lastTime) > 5000)
{
// Message: Ok, you can do action now.
}else{
// Message: Have to wait 5 seconds to do action.
return;
}
lastTime = System.currentTimeMillis();
But as we all know, System.currentTimeMillis() returns a long, and that long can keep increasing until it turns negativ..
My code should run on a server that need to have more than 1 month of uptime. So I'm afraid at some point System.currentTimeMillis() will return a negativ value and my code will always tell the user that he need to wait 5 seconds or the opposite.
I'm having real hard time to concentrate on this piece of code and fix it, so I'm asking you guys if you have a tip on how to fix this problem and make my code 100% safe.
Don't worry about it.
You know whos problem it is?
The guy who will need to update it on Sun Aug 17 03:12:55 GMT-04:00 292278994.
A long in milliseconds can represent 292 277 266 years. I'm not sure this is the kind of thing you need to be worried about.
According to this thread, it will overflow in year 292278994. I will say it is plenty of time:)
As everyone has said don't worry about it but for future reference maybe you'd prefer to use Joda-Time to ask this kind of question.
import org.joda.time.DateTime;
if(lastTime.plusSeconds(5).isAfterNow()) {
// Message: Ok, you can do action now.
}
else {
// Message: Have to wait 5 seconds to do action.
return;
}
lastTime = new DateTime();
System.currentTimeMillis() returns the time in milliseconds, between the current time and midnight, January 1, 1970 UTC. With the largest maximum value that can be represented as a long is 9,223,372,036,854,775,807, if my calculation is right (long max / (1000 * 3600 * 24 * 365)), that could go up to more than 292471208 years. If your program can survive that long, let someone who will be born that many years later worry about it like we did for Y2K.
Even though the time it will overflow is far, far into the future as others have stated. It won't even be a problem then because you are taking the difference of two times. e.g. say you take the year 292,278,994 and the year 292,278,995 (which would appear to be negative), the difference is only 1 year (a positive number) e.g. if you take
long overflowYear = Long.MIN_VALUE; // overvflow of Long.MAX_VALUE + 1
long okayYear = Long.MAX_VALUE;
// time = 1 (positive due to an underflow!)
long time = overflowYear - okayYear;
This sort of this could happen with System.nanoTime() as it doesn't have a defined starting time and ticks one million time faster. However as long as you take the time difference, it doesn't matter if one is negative or positive provided they are less than 292 years apart.
So in answer to your question, even after the year 292,278,994 you won't have a problem until the application have been running for more than 292,278,994 years between calls to System.currentTimeMillis() !