What are these numbers used for chinese lunar calendar conversions? - calendar

I'm developing an application about bank holidays in many countries.
To find bank holidays dates in China I need to convert dates to Chinese system.
I have found many libraries in different languages, like :
this one : https://github.com/v5developer/maven-framework-project/blob/master/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java that I transposed to Apex language
this one https://www.javascriptbank.com/javascript/time/Lunar_Calendar_script/amlich-hnd.js in js (it's for Vietnam but seems to work about the same)
or this one https://github.com/magiclen/JavaChineseCalendar/blob/master/src/main/java/org/magiclen/%E8%BE%B2%E6%9B%86/%E8%BE%B2%E6%9B%86.java
and more.
All of them use an array of numbers, with one number per year, like this one :
final static long[] lunarInfo = new long[] { 0x04bd8, 0x04ae0, 0x0a570,
0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0,
0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50,
0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,
0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0,
0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4,
0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550,
0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950,
0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0,
0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40,
0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3,
0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,
0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0,
0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9,
0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0,
0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65,
0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,
0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2,
0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 };
used to calculate various numbers, like in
final private static int yearDays(int y) {
int i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
if ((lunarInfo[y - 1900] & i) != 0)
sum += 1;
}
return (sum + leapDays(y));
}
final private static int leapDays(int y) {
if (leapMonth(y) != 0) {
if ((lunarInfo[y - 1900] & 0x10000) != 0)
return 30;
else
return 29;
} else
return 0;
}
I've been searching in libraries comments, documentations, gerneral info about China, and I learnt a lot about the chinese calendar but couldn't find what these numbers are.... and where they come from.
It doesn't prevent me from using it but I like to understand what I code... Any explanations ?
Thanks

I finally came to understand that, at least for this code https://github.com/v5developer/maven-framework-project/blob/master/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java, it's just a way to store data :
The data is encoded on 17 bits with :
bit 17 : number of days in leap month , 1=>30, 0=>29
bits 16 to 5 : number of days in each month, 0=>29, 1=>30
bits 4 to 1 : number of the leap month in the year in binary.
So 0x16554 (7th in the list, so year 1906) is 10110010101010100 in binary with a 17 bits length, which means :
10110010101010100 : There is a leap month, it's month 4
10110010101010100 : The leap month has 30 days
10110010101010100 : The 1st month has 29 days
10110010101010100 : The 2nd month has 30 days
...
10110010101010100 : The 12th month has 30 days
which can be checked here : https://www.asia-home.com//china/calendrier-chinois/year/1906.php
In other codes the meaning can vary but the idea is the same.

Related

Parking fee using C

Beginner here. I just wanted to know how and where I went wrong with this code. I’m having problem with using the modulo for the time. The following is the problem and the code I created.
A company wants to create a system that automatically computes for the total fee of the parking services in their new mall.
The user first needs to input their vehicle type, time-in and time-out. Then, it will compute for the total fee of the parking service based on the time the vehicle spent parked. Use the table below as basis:
Vehicle Type First 3 hours After 3 hours
M-otorcycle FREE PHP 10.00/hr
C-ar PHP 30.00 PHP 10.00/hr
T-ruck PHP 50.00 PHP 25.00/hr
Assumptions:
User will not input a value wherein Timeout < Timein.
Max Inputs will for time will be from 0000 to 2359, and it will always follow that form (user will not input values like 13, 17, 110).
Input Format
Vehicle Type, Time-in, and Time-out
Input Sample
M
1230
1430
Output Format
Payment, hours and minutes in this format.
Output Sample
Payment:·0.00
Hours:·2
Minutes:·0
Code:
#include<stdio.h>
int main()
{
double payment;
int time, entry,exit;
int hours, minutes;
char type;
scanf("%c %d %d", &type, &entry, &exit);
hours = (exit-entry)/100;
minutes = (exit-entry) %60;
if (type == 'M' && time > 3)
payment = hours*10;
else
payment = hours*0;
if (type=='C' && time >= 3)
payment = ((hours-3)*10)+30;
else
payment = 30;
if (type == 'T' && hours >= 3)
payment = ((hours-3)*25)+50;
else
payment = 50;
printf("Payment: %.2f \nHours: %d \nMinutes: %d ", payment, hours, minutes);
return 0;
}
Can u send the table clearly.
And also,
minutes = abs((exit/100) - (entry/100));
No use of modulus!

Why does the sum of calendar days from 1. AD to 1.1.2001 differ from tropical days by 3?

As a little background: in October 1582 the Gregorian calendar was introduced to correct problems with the Julian calendar, which was in use until then. The Gregorian calendar specifies the length of a year more precisely, adds a new leap year calculation and removes 10 days from the Julian calendar on transition (moving from 4.Oct.1582 to 15.Oct.1582)
// Julian leap year calculation
((year % 4) == 0)
// Gregorian leap year calculation
((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0)
To sum up all calendar days from 1 AD to 2001 AD I use:
#include <stdio.h>
int main( void)
{
int year;
int daysInYear;
int total;
total = 0;
for( year = 1; year <= 2001; year++)
{
//
daysInYear = 365;
if( year < 1582)
daysInYear += ((year % 4) == 0);
else
if( year > 1582)
daysInYear += ((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0);
else
daysInYear -= 10; // 1582 exactly
total += daysInYear;
printf( "%d: +%d = %d\n", year, daysInYear, total);
}
return( 0);
}
Now running this exhaustively over all years from 1 to 2000 gives this pastebin: https://pastebin.com/bR7hwNr1
The most interesting bits show that the leap year and day-skip calculation is correct and also produces the result:
1: +365 = 365
2: +365 = 730
3: +365 = 1095
4: +366 = 1461
...
100: +366 = 36525
...
400: +366 = 146100
...
1581: +365 = 577460
1582: +355 = 577815
1583: +365 = 578180
...
1900: +365 = 693962
...
1996: +366 = 729026
1997: +365 = 729391
1998: +365 = 729756
1999: +365 = 730121
2000: +366 = 730487
Now the question is this: the 1.1.2001 is at 730487 elapsed calendar days. Given the length of the year as defined by the Gregorian calendar as 365.2425, I would expect to see 2000*365.2425 = 730485 days. If one uses tropical days or solar days it would be 730484. But 740487 is clearly out of range.
Assuming that no-one miscounted any days in the Gregorian Calendar range, there are some extra days in the Julian Calendar, that don't match with the tropical days. But the Gregorian was created to correct the Julian calendar and I don't think they would have made that large an error in 1582.
This could be more a historical question than a programming question I would guess.
The goal of the Gregorian reform of the calendar was to reset the date of the northern hemisphere vernal equinox to March 21, and keep it there. This date was chosen because that was the approximate average date of the equinox at the time of the Council of Nicaea in AD 325. At the time of the council, the date of the equinox had slipped from about March 25 in AD 1.
For all the details read the book Gregorian Reform of the Calendar which is the proceedings of a conference held by the Vatican Observatory and published in 1983.
To clarify, when evaluating the Gregorian calendar compared to the Julian, using a mix of Julian and Gregorian dates incorporates the one-time correction of 10 days which was intended to correct for accumulated excess leap years from about AD 325 to AD 1582. If one wishes to use some start date other than AD 325, the entire calculation should use ONLY Gregorian dates or ONLY Julian dates.

C difference between days 1 day not working

For a project im developing i need to find a diference between two dates to check which is more recent, and i was doing just fine but i found a little bug.
for the dates im using struct tm, this is the code:
it works in every date except when i want to compare a date in the end of the month like (31/5/2016) with the following day (1/6/2016), it returns me 0 days and it should return 1. but if i change it to 30/5/2016 it returns 1 day instead of 2. The thing is may is 31 days not 30.. so it works in some months and in others it doesnt work.. does anyone know how to get past this?
thanks in advance and sorry for my bad english, it isn't my native language
The value 0, not 1, in secondDate.tm_mon will stand for January.
Try this:
struct tm firstDate, secondDate;
firstDate.tm_hour = 0;
firstDate.tm_min = 0;
firstDate.tm_sec = 0;
firstDate.tm_mon = 5 - 1;
firstDate.tm_mday = 30;
firstDate.tm_year = 2016 - 1900; //difference between current year and 1900
secondDate.tm_hour = 0;
secondDate.tm_min = 0;
secondDate.tm_sec = 0;
secondDate.tm_mon = 6 - 1;
secondDate.tm_mday = 1;
secondDate.tm_year = 2016 - 1900;
time_t fDate = mktime(&firstDate); // 31/5/2016
time_t sDate = mktime(&secondDate); // 1/6/2016
int diff = (difftime(fDate, sDate));
printf("%d", diff / 86400);

C beginner help : day of week for any given date

The prompt is:
Implement a function that reads in a string containing a textual description of a cal- endar date and that prints out the corresponding day of the week (Monday–Sunday). The two valid input formats for this function are:
mm/dd/yyyy
Example: 03/04/2014
Output: Tuesday
Month dd, yyyy
Example: March 04, 2014
Output: Tuesday
where dd is the numeric day, mm is the numeric month, yyyy is the year and Month is the name of the month. All days and months are specified using two digits (i.e. for March, use 03 instead of 3). In the second valid format, there is a single space between Month and dd and between dd, and yyyy.
In order to receive full credit on this task, your program should print out the correct day of the week for any input in a correct format.
So as of right now i am able to get the correct days for every single day except in the years 2005 2009 2013 2017 etc etc... they are always a day behind, i notice that its going by a trend of every 4 years the days end up 1 day behind. Im not sure whats wrong. is it cause my method of using 365.25 as each year is wrong?
My code:
#include<stdio.h>
int main()
{
int month,day1,day2,totdays,year,dm,dn,leap,rmd;
printf(" ");
scanf("%d/%d/%d",&month,&day1,&year);
if(((year%4==0) && (year%100!=0)) || (year%400==0))
{
if(month==1)
dm=0;
if(month==2)
dm=31;
if(month==3)
dm=60;
if(month==4)
dm=91;
if(month==5)
dm=121;
if(month==6)
dm=152;
if(month==7)
dm=182;
if(month==8)
dm=213;
if(month==9)
dm=244;
if(month==10)
dm=274;
if(month==11)
dm=305;
if(month==12)
dm=335;
}
else
{
if(month==1)
dm=0;
if(month==2)
dm=31;
if(month==3)
dm=59;
if(month==4)
dm=90;
if(month==5)
dm=120;
if(month==6)
dm=151;
if(month==7)
dm=181;
if(month==8)
dm=212;
if(month==9)
dm=243;
if(month==10)
dm=273;
if(month==11)
dm=304;
if(month==12)
dm=334;
}
day2=(year-1970)*(365.25);
dn=dm+day1;
totdays=day2+dn;
rmd=totdays%7;
if(rmd==5)
{
printf("Monday \n");
}
if(rmd==6)
{
printf("Tuesday \n");
}
if(rmd==0)
{
printf("Wednesday \n");
}
if(rmd==1)
{
printf("Thursday \n");
}
if(rmd==2)
{
printf("Friday \n");
}
if(rmd==3)
{
printf("Saturday \n");
}
if(rmd==4)
{
printf("Sunday \n");
}
return 0;
}
1969 wasn't a leap year, 1972 was. When you do
day2=(year-1970)*(365.25);
to discover how many days off January 1st of year year is, you'll count
0 days for '70
365.25 days for '71
730.5 days for '72
1095.75 days for '73
1461 days for '74
The fractional portion of the floating point calculation is truncated, so day2 isn't going to count the extra day from 02/29/1972 until 01/01/1974, instead of 01/01/1973 as it should.
Put another way, you are making the assumption that 1970 was the first year after a leap year, so a leap day won't be counted until four years later.
The day2 calculation won't work. There are 1461 days in every four year period. First you need to compute how many 4 year periods have passed. Then figure out how many days there were to the beginning of the specified year, similar to what you did for the months.
The year%100 and year%400 exceptions add a little complexity, but fortunately the year 2000 was a leap year, so the first time you have to deal with that little wrinkle is the year 2100.

How to make ISO8601 produce Hebrew day of the year, week of the year?

Can someone think of a way to calculate the Day-of-the-Year and Week-of-the-Year for the Hebrew calendar? I'm using ISO 8601 which can return the Hebrew year, month, day of the month and day of the week. I'm trying to write re-usable code to calculator any Torah portion (Parsha).
Take a look at the hebcal command to do this. There are also ports for JavaScript (shameless plug, it was written by me), Java, and Perl.
This is easy if you can use Java. My library Time4J enables the features you want (in Hebrew calendar):
PlainDate iso8601 = Iso8601Format.parseDate("2018-03-16");
HebrewCalendar hc = iso8601.transform(HebrewCalendar.axis());
int hyear = hc.getYear();
HebrewMonth hmonth = hc.getMonth(); // obtains an enum
int hdayOfMonth = hc.getDayOfMonth();
Weekday hdayOfWeek = hc.getDayOfWeek(); // obtains an enum
int hdayOfYear = hc.getDayOfYear();
int weekOfYear =
hc.get(
CommonElements.weekOfYear(
HebrewCalendar.axis(),
HebrewCalendar.getDefaultWeekmodel()
)
);
System.out.println("year=" + hyear); // 5778
System.out.println("month=" + hmonth); // ADAR_II (technical result, see next line)
System.out.println(
"month=" + hmonth.getDisplayName(Locale.ENGLISH, hc.isLeapYear())); // Adar
System.out.println("day-of-month=" + hdayOfMonth); // 29
System.out.println("day-of-week=" + hdayOfWeek); // FRIDAY
System.out.println("day-of-year=" + hdayOfYear); // 207
System.out.println("week-of-year=" + weekOfYear); // 30
There are many more features, for example taking into account start of day in the evening of previous day (including astronomical calculations of sunset) or hebrew biblical clock time or different numbering schemes for months etc.

Resources