I need to convert from a standard Gregorian date to a Julian day number.
I've seen nothing documented in C# to do this directly, but I have found many posts (while Googling) suggesting the use of ToOADate.
The documentation on ToOADate does not suggest this as a valid conversion method for Julian dates.
Can anyone clarify if this function will perform conversion accurately, or perhaps a more appropriate method to convert DateTime to a Julian formatted string.
This provides me with the expected number when validated against Wikipedia's Julian Day page
public static long ConvertToJulian(DateTime Date)
{
int Month = Date.Month;
int Day = Date.Day;
int Year = Date.Year;
if (Month < 3)
{
Month = Month + 12;
Year = Year - 1;
}
long JulianDay = Day + (153 * Month - 457) / 5 + 365 * Year + (Year / 4) - (Year / 100) + (Year / 400) + 1721119;
return JulianDay;
}
However, this is without an understanding of the magic numbers being used.
Thanks
References:
DateTime.ToOADate Method
OADate is similar to Julian Dates, but uses a different starting point (December 30, 1899 vs. January 1, 4713 BC), and a different 'new day' point. Julian Dates consider noon to be the beginning of a new day, OADates use the modern definition, midnight.
The Julian Date of midnight, December 30, 1899 is 2415018.5. This method should give you the proper values:
public static double ToJulianDate(this DateTime date)
{
return date.ToOADate() + 2415018.5;
}
As for the algorithm:
if (Month < 3) ...: To make the magic numbers work our right, they're putting February at the 'end' of the year.
(153 * Month - 457) / 5: Wow, that's some serious magic numbers.
Normally, the number of days in each month is 31 28 31 30 31 30 31 31 30 31 30 31, but after that adjustment in the if statement, it becomes 31 30 31 30 31 31 30 31 30 31 31 28. Or, subtract 30 and you end up with 1 0 1 0 1 1 0 1 0 1 1 -2. They're creating that pattern of 1s and 0s by doing that division in integer space.
Re-written to floating point, it would be (int)(30.6 * Month - 91.4). 30.6 is the average number of days per month, excluding February (30.63 repeating, to be exact). 91.4 is almost the number of days in 3 average non-February months. (30.6 * 3 is 91.8).
So, let's remove the 30, and just focus on that 0.6 days. If we multiply it by the number of months, and then truncate to an integer, we'll get a pattern of 0s and 1s.
0.6 * 0 = 0.0 -> 0
0.6 * 1 = 0.6 -> 0 (difference of 0)
0.6 * 2 = 1.2 -> 1 (difference of 1)
0.6 * 3 = 1.8 -> 1 (difference of 0)
0.6 * 4 = 2.4 -> 2 (difference of 1)
0.6 * 5 = 3.0 -> 3 (difference of 1)
0.6 * 6 = 3.6 -> 3 (difference of 0)
0.6 * 7 = 4.2 -> 4 (difference of 1)
0.6 * 8 = 4.8 -> 4 (difference of 0)
See that pattern of differences in the right? That's the same pattern in the list above, the number of days in each month minus 30. The subtraction of 91.8 would compensate for the number of days in the first three months, that were moved to the 'end' of the year, and adjusting it by 0.4 moves the successive differences of 1 (0.6 * 4 and 0.6 * 5 in the above table) to align with the adjacent months that are 31 days.
Since February is now at the 'end' of the year, we don't need to deal with its length. It could be 45 days long (46 on a leap year), and the only thing that would have to change is the constant for the number of days in a year, 365.
Note that this relies on the pattern of 30 and 31 month days. If we had two months in a row that were 30 days, this would not be possible.
365 * Year: Days per year
(Year / 4) - (Year / 100) + (Year / 400): Plus one leap day every 4 years, minus one every 100, plus one every 400.
+ 1721119: This is the Julian Date of March 2nd, 1 BC. Since we moved the 'start' of the calendar from January to March, we use this as our offset, rather than January 1st. Since there is no year zero, 1 BC gets the integer value 0. As for why March 2nd instead of March 1st, I'm guessing that's because that whole month calculation was still a little off at the end. If the original writer had used - 462 instead of - 457 (- 92.4 instead of - 91.4 in floating point math), then the offset would have been to March 1st.
While the method
public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }
works for modern dates, it has significant shortcomings.
The Julian date is defined for negative dates - i.e, BCE (before common era) dates and is common in astronomical calculations. You cannot construct a DateTime object with the year less than 0, and so the Julian Date cannot be computed for BCE dates using the above method.
The Gregorian calendar reform of 1582 put an 11 day hole in the calendar between October 4th and the 15th. Those dates are not defined in either the Julian calendar or the Gregorian calendar, but DateTime accepts them as arguments. Furthermore, using the above method does not return the correct value for any Julian date. Experiments with using the System.Globalization.JulianCalendar.ToDateTime(), or passing the JulianCalendar era into the DateTime constructor still produce incorrect results for all dates prior to October 5, 1582.
The following routines, adapted from Jean Meeus' "Astronomical Algorithms", returns correct results for all dates starting from noon on January 1st, -4712, time zero on the Julian calendar. They also throw an ArgumentOutOfRangeException if an invalid date is passed.
public class JulianDate
{
public static bool isJulianDate(int year, int month, int day)
{
// All dates prior to 1582 are in the Julian calendar
if (year < 1582)
return true;
// All dates after 1582 are in the Gregorian calendar
else if (year > 1582)
return false;
else
{
// If 1582, check before October 4 (Julian) or after October 15 (Gregorian)
if (month < 10)
return true;
else if (month > 10)
return false;
else
{
if (day < 5)
return true;
else if (day > 14)
return false;
else
// Any date in the range 10/5/1582 to 10/14/1582 is invalid
throw new ArgumentOutOfRangeException(
"This date is not valid as it does not exist in either the Julian or the Gregorian calendars.");
}
}
}
static private double DateToJD(int year, int month, int day, int hour, int minute, int second, int millisecond)
{
// Determine correct calendar based on date
bool JulianCalendar = isJulianDate(year, month, day);
int M = month > 2 ? month : month + 12;
int Y = month > 2 ? year : year - 1;
double D = day + hour/24.0 + minute/1440.0 + (second + millisecond / 1000.0)/86400.0;
int B = JulianCalendar ? 0 : 2 - Y/100 + Y/100/4;
return (int) (365.25*(Y + 4716)) + (int) (30.6001*(M + 1)) + D + B - 1524.5;
}
static public double JD(int year, int month, int day, int hour, int minute, int second, int millisecond)
{
return DateToJD(year, month, day, hour, minute, second, millisecond);
}
static public double JD(DateTime date)
{
return DateToJD(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond);
}
}
If someone need to convert from Julian date to DateTime , see below :
public static DateTime FromJulianDate(double julianDate)
{
return DateTime.FromOADate(julianDate - 2415018.5);
}
The explanation by David Yaw is spot on, but calculation of the cumulative number of days of the year for the months prior to the given month is anti-intuitive. If you prefer an array of integers to make the algorithm more clear then this will do:
/*
* convert magic numbers created by:
* (153*month - 457)/5)
* into an explicit array of integers
*/
int[] CumulativeDays = new int[]
{
-92 // Month = 0 (Should not be accessed by algorithm)
, -61 // Month = 1 (Should not be accessed by algorithm)
, -31 // Month = 2 (Should not be accessed by algorithm)
, 0 // Month = 3 (March)
, 31 // Month = 4 (April)
, 61 // Month = 5 (May)
, 92 // Month = 6 (June)
, 122 // Month = 7 (July)
, 153 // Month = 8 (August)
, 184 // Month = 9 (September)
, 214 // Month = 10 (October)
, 245 // Month = 11 (November)
, 275 // Month = 12 (December)
, 306 // Month = 13 (January, next year)
, 337 // Month = 14 (February, next year)
};
and the first thre lines of the calculation then become:
int julianDay = day
+ CumulativeDays[month]
+ 365*year
+ (year/4)
The expression
(153*month - 457)/5)
though produces the exact same sequence same integers as the array above for values in the range: 3 to 14; inclusive and does so with no storage requirements. The lack of storage requirements is only virtue in calculating the cumulative number of days in such and obfuscated way.
My code for modified Julian Date uses the same algorithm but a different magic number on the end so that the resulting value matches the Modified Julian Date shown on Wikipedia. I have been using this same algorithm for at least 10 years as the key for daily time series (originally in Java).
public static int IntegerDate(DateTime date)
{
int Month = date.Month;
int Day = date.Day;
int Year = date.Year;
if (Month < 3)
{
Month = Month + 12;
Year = Year - 1;
}
//modified Julian Date
return Day + (153 * Month - 457) / 5 + 365 * Year + (Year / 4) - (Year / 100) + (Year / 400) - 678882;
}
The reverse calculation has more magic numbers for your amusement:
public static DateTime FromDateInteger(int mjd)
{
long a = mjd + 2468570;
long b = (long)((4 * a) / 146097);
a = a - ((long)((146097 * b + 3) / 4));
long c = (long)((4000 * (a + 1) / 1461001));
a = a - (long)((1461 * c) / 4) + 31;
long d = (long)((80 * a) / 2447);
int Day = (int)(a - (long)((2447 * d) / 80));
a = (long)(d / 11);
int Month = (int)(d + 2 - 12 * a);
int Year = (int)(100 * (b - 49) + c + a);
return new DateTime(Year, Month, Day);
}
The below method gives you the julian days starting from 1995/1/1, 00:00:00
/// <summary>
/// "GetJulianDays" will return a Julian Days starting from date 1 Jan 1995
/// </summary>
/// <param name="YYYYMMddHHmmss"></param>
/// <returns>Julian Day for given date</returns>
public string GetJulianDays(DateTime YYYYMMddHHmmss)
{
string DateTimeInJulianFormat = string.Empty;
DateTime julianStartDate = new DateTime(1995, 1, 1, 00, 00, 00); //YYYY,MM,dd,HH,mm,ss
DateTime DateTimeNow = YYYYMMddHHmmss;
double difference = (DateTimeNow - julianStartDate).TotalDays;
int totalDays = int.Parse(difference.ToString());
DateTimeInJulianFormat = string.Format("{0:X}", totalDays);
return DateTimeInJulianFormat;
}
I use some calculations in microcontrollers but require years only between 2000 and 2255.
Here is my code:
typedef struct {
unsigned int8 seconds; // 0 to 59
unsigned int8 minutes; // 0 to 59
unsigned int8 hours; // 0 to 23 (24-hour time)
unsigned int8 day; // 1 to 31
unsigned int8 weekday; // 0 = Sunday, 1 = Monday, etc.
unsigned int8 month; // 1 to 12
unsigned int8 year; // (2)000 to (2)255
unsigned int32 julian; // Julian date
} date_time_t;
// Convert from DD-MM-YY HH:MM:SS to JulianTime
void JulianTime(date_time_t * dt)
{
unsigned int8 m, y;
y = dt->year;
m = dt->month;
if (m > 2) m -= 3;
else {
m += 9;
y --;
}
dt->julian = ((1461 * y) / 4) + ((153 * m + 2) / 5) + dt->day;
dt->weekday = ( dt->julian + 2 ) % 7;
dt->julian = (dt->julian * 24) + (dt->hours );
dt->julian = (dt->julian * 60) + (dt->minutes );
dt->julian = (dt->julian * 60) + (dt->seconds );
}
// Reverse from JulianTime to DD-MM-YY HH:MM:SS
void GregorianTime(date_time_t *dt)
{
unsigned int32 j = dt->julian;
dt->seconds = j % 60;
j /= 60;
dt->minutes = j % 60;
j /= 60;
dt->hours = j % 24;
j /= 24;
dt->weekday = ( j + 2 ) % 7; // Get day of week
dt->year = (4 * j) / 1461;
j = j - ((1461 * dt->year) / 4);
dt->month = (5 * j - 3) / 153;
dt->day = j - (((dt->month * 153) + 3) / 5);
if ( dt->month < 10 )
{
dt->month += 3;
}
else
{
dt->month -= 9;
dt->year ++;
}
}
Hope this helps :D
The wikipedia page you linked contain the code for conversion from either the Julian or the Gregorian calendars. E.g. you can choose to convert a date prior to the Gregorian calendar era, which is called 'the proleptic Gregorian calendar'.
Depending on the chosen 'conversion' calendar the output will vary. This is because the calendars themselves are different constructs and deals with alignments/corrections of various sorts in different ways.
public enum ConversionCalendar
{
GregorianCalendar,
JulianCalendar,
}
public static int ConvertDatePartsToJdn(int year, int month, int day, ConversionCalendar conversionCalendar)
{
switch (conversionCalendar)
{
case ConversionCalendar.GregorianCalendar:
return ((1461 * (year + 4800 + (month - 14) / 12)) / 4 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4 + day - 32075);
case ConversionCalendar.JulianCalendar:
return (367 * year - (7 * (year + 5001 + (month - 9) / 7)) / 4 + (275 * month) / 9 + day + 1729777);
default:
throw new System.ArgumentOutOfRangeException(nameof(calendar));
}
}
One can also convert back from JDN to date components:
public static void ConvertJdnToDateParts(int julianDayNumber, ConversionCalendar conversionCalendar, out int year, out int month, out int day)
{
var f = julianDayNumber + 1401;
if (conversionCalendar == ConversionCalendar.GregorianCalendar)
f += (4 * julianDayNumber + 274277) / 146097 * 3 / 4 + -38;
var eq = System.Math.DivRem(4 * f + 3, 1461, out var er);
var hq = System.Math.DivRem(5 * (er / 4) + 2, 153, out var hr);
day = hr / 5 + 1;
month = ((hq + 2) % 12) + 1;
year = eq - 4716 + (14 - month) / 12;
}
These methods were created from the code on wikipedia, so they should work, unless I fumbled something up.
Per definition on 1.1.2000 at 11:58:55,800 UTC (J2000.0)
exactly 2451545 JD (julian days) had passed since the very first day.
const long J2000UtcTicks = 630823247358000000L; // (new DateTime(2000,1,1,11,58,55,800)).Ticks
const double TicksPerDay = 24 * 60 * 60 * 1E7; // 100ns is equal to 1 tick
// to convert any
DateTime dt;
// you need to convert to timezone GMT and calc the ticks ...
double ticks = dt.ToUniversalTime().Ticks - J2000UtcTicks;
return 2451545d + ticks / TicksPerDay;
in razo pages:
code:
ViewData["jul"] = DateTime.Now.ToOADate() + 2415018.5;
view:
#ViewData["jul"]
in view only:
#{Double jday= DateTime.Now.ToOADate() + 2415018.5;}
#jday
The following function converts a date to Julian date that matches that of Tradestation Easylanguage:
public double ToJulianDate(DateTime date) { return date.ToOADate(); }
Related
I have a situation where in I have time strings like
10:20:70
11:65:40
I need to convert them into proper time in hh:mm:ss format using c# console.
For eg : 10:20:70 will be 10:21:10 after fixing
26:12:20 will be 02:12:10 as 26hours to be considered as 2 hours
How to achieve this? Please help me out.
Any help would be appreciated
Split the input and and either use a TimeSpan to get the real representation of the input.
Or use modulo operator % to fix the overflow.
var split = date.Split(":").Select(int.Parse).ToArray();
if(split.Count() != 3) {Console.WriteLine("bad format"); continue;}
/// public TimeSpan (int hours, int minutes, int seconds);
var realTimeSpanRepresentation = new TimeSpan(split[0],split[1],split[2]);
var correctedTimeSpanRepresentation = new TimeSpan(split[0]%24,split[1]%60,split[2]%60);
Console.WriteLine(date+" => "+realTimeSpanRepresentation+" / "+correctedTimeSpanRepresentation);
/// public DateTime (int year, int month, int day, int hour, int minute, int second);
//var realDateTimeRepresentation = new DateTime(1,1,1,split[0],split[1],split[2]); // Will go boom cause overflow
var correctedDateTimeRepresentation = new DateTime(1,1,1,split[0]%24,split[1]%60,split[2]%60);
Console.WriteLine(date+" => "+correctedDateTimeRepresentation);
Result:
10:20:70 => 10:21:10 / 10:20:10
10:20:70 => 01/01/0001 10:20:10
11:65:40 => 12:05:40 / 11:05:40
11:65:40 => 01/01/0001 11:05:40
99:99:99 => 4.04:40:39 / 03:39:39
99:99:99 => 01/01/0001 03:39:39
demo: https://dotnetfiddle.net/Uwb4zc
NB: I nammed it real representation, cause Imo "00:60:00" is one Hour not "00:00:00"
Here is a method that takes a total amount of seconds and gives proper values for how many years, days, hours, minutes and seconds in there.
public static void GetTimeFromSeconds(float secondsTotal, out int s, out int m, out int h, out int d, out int y)
{
s = m = h = d = y = 0;
s = (int)(secondsTotal % 60);
// substruct the seconds remainder from the total amount (75 - 15 = 60, 125 - 5 = 120).
secondsTotal -= s;
// if nothing left then it was less than 1 minute (45 - 0 = 45).
if (secondsTotal < 60)
return;
// secondsTotal / 60 => how many minutes total
// % 60 => how many minutes remain after splitting to whole hours
m = (int)(secondsTotal / 60 % 60);
// substruct the minutes remainder from the total amount (every minute takes 60 secs from the total)
secondsTotal -= m * 60;
// if there's not enough seconds remain in the total to get at least 1 whole hour (3600 secs)
// then it means there was less than 1 hour.
if (secondsTotal < 3600)
return;
// secondsTotal / 3600 => how many hours total
// % 24 => what will remain after splitting to whole days (24 hours)
h = (int)(secondsTotal / 3600 % 24);
// every whole hour takes 3600 secs from the total
secondsTotal -= h * 3600;
// 24 hours = 86400 seconds.
// If there's less remaining than it was less than 24 hours.
if (secondsTotal < 86400)
return;
// secondsTotal/ 86400 => how many days total
// % 365 => how many will remain after splitting to years
d = (int)(secondsTotal / 86400 % 365);
// substruct whole days
secondsTotal -= d * 86400;
// 1 year = 31536000 secs.
// is there enough secs remaining to get a whole year?
if (secondsTotal < 31536000)
return;
y = (int)(secondsTotal / 31536000);
}
So, you could parse your time into separate values
26:70:20 => hours=26, minutes=70, seconds=20
then count the total amount of seconds:
secondsTotal = hours * 3600 + minutes * 60 + seconds
and then use the method above:
int years, days, hours, mins, secs;
GetTimeFromSeconds(secondsTotal, out secs, out mins, out hours, out days, out years);
For 26 hours, 70 mins, 20 secs the results will be days: 1, hours: 3, minutes: 10, secs: 20.
Then format it into the format you need. For example:
TimeSpan properTime = new TimeSpan(hours, mins, secs);
properTime.ToString(#"hh\:mm\:ss");
How can I get the date of next coming Monday or next coming Friday in C#.
lets say today is Wednesday and I want to get date of coming Friday.
This is what I've done
DateTime time = DateTime.Now.Date;
DateTime NextFriday;
if (time.DayOfWeek == DayOfWeek.Wednesday)
{
NextFriday = DateTime.Now.AddDays(2);
}
with this approach I've to initiate 7 variables for each day and 7 conditions for ever day to find the next specific day.
Is there any better and clean code by which I can get the date of any of the next coming day.
Using the following
public int CalculateOffset(DayOfWeek current, DayOfWeek desired) {
// f( c, d ) = [7 - (c - d)] mod 7
// f( c, d ) = [7 - c + d] mod 7
// c is current day of week and 0 <= c < 7
// d is desired day of the week and 0 <= d < 7
int c = (int)current;
int d = (int)desired;
int offset = (7 - c + d) % 7;
return offset == 0 ? 7 : offset;
}
You can calculate how far you are from the desired day and then add that to the current date
DateTime now = DateTime.Now.Date;
int offset = CalculateOffset(now.DayOfWeek, DayOfWeek.Friday);
DateTime nextFriday = now.AddDays(offset);
DateTime today = DateTime.Today;
DateTime nextFriday = System.Linq.Enumerable.Range(0, 6)
.Select(i => today.AddDays(i))
.Single(day => day.DayOfWeek == DayOfWeek.Friday);
You should probably use a time library that supports this, such as NodaTime.
See date.Next(IsoDayOfWeek.Sunday) on https://nodatime.org/1.3.x/userguide/arithmetic
Here's an alternative solution (please don't use this):
DateTime F(DateTime t, DayOfWeek dayOfWeek) => t.AddDays((7 + (int)dayOfWeek - (int)t.DayOfWeek) % 7);
for (int i = 0; i < 7; i++)
Console.WriteLine((DayOfWeek)i + " " + F(DateTime.Now, (DayOfWeek)i));
Outputs (on Wednesday 4/25/2018):
Sunday 4/29/2018 12:00:00 AM
Monday 4/30/2018 12:00:00 AM
Tuesday 5/1/2018 12:00:00 AM
Wednesday 4/25/2018 12:00:00 AM
Thursday 4/26/2018 12:00:00 AM
Friday 4/27/2018 12:00:00 AM
Saturday 4/28/2018 12:00:00 AM
DayOfWeek is just an enum between 0 and 6, so with modular arithmetic you can use the difference between your date of interest and target day of week to compute the number of days you must add.
A quick warning, you need to take into account timezone of interest when you ask what is meant by "today". It means a different thing depending on which side of the date line you live.
using System;
public class Program
{
public static DateTime NextDayForDay(DayOfWeek dayOfWeek, DateTime occurringAfter)
{
return occurringAfter.AddDays(((dayOfWeek - occurringAfter.DayOfWeek + 6) % 7)+1);
}
public static void Main()
{
for (int i=0; i < 7; i++)
{
for (int j=0; j < 7; j++)
{
DayOfWeek dayOfWeek = (DayOfWeek)(((int)DayOfWeek.Sunday + j) % 7);
DateTime test = DateTime.Today.AddDays(i);
Console.WriteLine($"{test}=>Next {dayOfWeek} is {NextDayForDay(dayOfWeek, test)}");
}
}
}
}
I have a start date like "2015-03-10". I want to add 1.25 days per month for the current year from this start date. For example, I have start date "2015-03-10" then for this year the number of days will be 12.50. (1.25 days for each month from March month).
Given date : 2015-11-10 need to add days up to March 31st,2016 : 1.25 * 5 (as from November month, here 5 )(For every month add 1.25 days) Number of days for this year : 6.25
(year start calculated from April and year end considered as March.)
How can i do this in c# can any one help me to do this
Thanks in advance
This example ignores the days of the months, as per your post:
DateTime start;
DateTime end;
// assuming end > start
double value = 1.25 * (end.Month - start.Month + 12 * (end.Year - start.Year) + 1);
EDIT: I can help you to understand this line of code splitting in some steps:
DateTime start = DateTime.Now;
DateTime end = new DateTime(start.Year, 3, 31);
if (start.Month > 3)
end = end.AddYear(1);
double years = end.Year - start.Year;
double months = end.Month - start.Month + 1;
months += (years * 12);
double value = 1.25 * months;
I got it by following :
DateTime endDate = new DateTime(DateTime.Today.Year + 1, 4, 1).AddDays(-1);
if (Convert.ToDateTime(empHiredDate).Month > 4)
{
finMonth = Convert.ToDateTime(empHiredDate).Month - 4;
finMonth = 12 - finMonth;
avail =Convert.ToString(finMonth * 1.25);
}
else if (Convert.ToDateTime(empHiredDate).Month < 3)
{
finMonth = Convert.ToDateTime(empHiredDate).Month + 8;
finMonth = 12 - finMonth;
avail = Convert.ToString(finMonth * 1.25);
}
else if (Convert.ToDateTime(empHiredDate).Month == 4)
{
avail = Convert.ToString(12 * 1.25);
}
else if (Convert.ToDateTime(empHiredDate).Month == 3)
{
avail = Convert.ToString(1 * 1.25);
}
I have the following code to divide an amount by a number and allocate the result as an amount that needs to be paid per month.
objData.month_per_amount = (Convert.ToDecimal(txtAmount.Value) / Convert.ToInt32(txtMonths.Value));
In a scenario example if I divide 13 by 3 and round off the result to 2 decimal places I get 4.33 for each month. But when I multiply 4.33 by 3 I am getting 12.99, which is not equivalent to 13. There is a discrepancy of 0.01. In this scenario how can I allocate like below:
month 1: 4.33
month 2: 4.33
month 3: 4.34
Hope I made it clear, the preferred code should only be executed if there is such a discrepancy, for example if 14 is to be divided by 2, we get 7 for each month and 7+7=14, so exactly the same figure we are getting here.
In accounting you'd often use something called 'reducing balance' for this. The idea is that you calculate the month's total, deduct it from the overall total and reduce the number of months. So something like:
decimal balance = 13m;
int months = 3;
int monthsRemaining = 3;
for (var i = 0; i < months; i++)
{
decimal thisMonth = Math.Round(balance / monthsRemaining, 2);
balance -= thisMonth;
monthsRemaining -= 1;
Console.WriteLine("Month {0}: {1}", i + 1, thisMonth);
}
This will result in 4.33, 4.34, 4.33.
The benefit of this method is that the rounding errors are distributed fairly evenly throughout the period rather than all in one month. For example, 100 over 24 months using that method would result in 23 payments of 4.17 and 1 of 4.09 whereas reducing balance would be 4.16 or 4.17 each month.
You do not have to check the remainder. A more efficient C# code (in terms of the required computation) would be like the following.
double amount = 13;
int months = 3;
int precision = 2;
double[] amountForEachMonth = new double[months];
double temp = Math.Round(amount / months, precision);
for (int i = 0 ; i < months - 1 ; i++)
amountForEachMonth[i] = temp;
amountForEachMonth[months - 1] = amount - (temp * (months - 1)) ;
You don't need to make it a special case when there is a discrepancy, you can simply always calculate the payment of the last month as what's left to pay to reach the total amount. If there is no discrepancy then it will be the same value anyway. Example:
int months = Convert.ToInt32(txtMonths.Value);
decimal amount = Convert.ToDecimal(txtAmount.Value);
month_per_amount = Decimal.Round(amount / months, 2);
decimal last_month = amount - (months - 1) * month_per_amount;
for (int month = 1; month <= months; month++) {
decimal monthly = month < months ? month_per_amount : last_month;
Console.WriteLine("Month {0}: {1}", month, monthly);
}
if " amount % month == 0 " , no discrepancy occures. otherwise, the last item should be a little more than others .
(The code here may have some syntax issues, I wanted to show you the algorithm.)
decimal amount = Convert.ToDecimal(txtAmount.Value);
int month = Convert.ToInt32(txtMonths.Value);
int n = 3;
decimal amounts[3];//n = 3
for (int i = 0 ; i < n-1 ; i++)
amounts[i] = amount / month;
if ( amount % month != 0 ) {
amounts[n-1] = amount - ( amount / month * (n-1) ) ;
else
amounts[n-1] = amount / month ;
I want to get a six digit number by user and spit it into 3 parts as(day, month, year)
Example:
int date=111213;
day =11;
month =12;
year =13;
I think I have to convert it into string then by using substring() I can do this.
Any easy Idea ??
How about:
// Assuming a more sensible format, where the logically most significant part
// is the most significant part of the number too. That would allow sorting by
// integer value to be equivalent to sorting chronologically.
int day = date % 100;
int month = (date / 100) % 100;
int year = date / 10000;
// Assuming the format from the question (not sensible IMO)
int year = date % 100;
int month = (date / 100) % 100;
int day = date / 10000;
(Do you have to store your data like this to start with? Ick.)
Storing a date as an integer like this isn't ideal, but if you must do it -- and you're sure that the number will always use the specified format -- then you can easily extract the day, month and year:
int day = date / 10000;
int month = (date / 100) % 100;
int year = date % 100;
You can do this with modular arithmetic:
int day = date / 10000;
int month = (date / 100) % 100;
int year = date % 100;
Here is the solution in Java with no optimization:
final int value = 111213;
int day;
int month;
int year;
day = value / 10000;
month = (value - (day * 10000)) / 100;
year = (value - (day * 10000)) - month * 100;