summaryrefslogtreecommitdiff
path: root/nuttx/lib/lib_gmtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/lib/lib_gmtimer.c')
-rw-r--r--nuttx/lib/lib_gmtimer.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/nuttx/lib/lib_gmtimer.c b/nuttx/lib/lib_gmtimer.c
index 2758acd1a..03e1a2058 100644
--- a/nuttx/lib/lib_gmtimer.c
+++ b/nuttx/lib/lib_gmtimer.c
@@ -163,15 +163,26 @@ static void clock_utc2julian(time_t jd, int *year, int *month, int *day)
#endif /* CONFIG_JULIAN_TIME */
#else/* CONFIG_GREGORIAN_TIME */
+/* Only handles dates since Jan 1, 1970 */
+
static void clock_utc2calendar(time_t days, int *year, int *month, int *day)
{
int value;
+ int min;
+ int max;
int tmp;
boolean leapyear;
- /* There must be a better way to do this than the brute for method below */
+ /* There is one leap year every four years, so we can get close with the
+ * following:
+ */
+
+ value = days / (4*365 + 1); /* Number of 4-years periods */
+ days -= value * (4*365 + 1); /* Remaining days */
+ value = 70 + (value << 2); /* 1970 plus the 4 year groups */
+
+ /* Then we will brute force the next 0-3 years */
- value = 70;
for (;;)
{
/* Is this year a leap year (we'll need this later too) */
@@ -203,43 +214,63 @@ static void clock_utc2calendar(time_t days, int *year, int *month, int *day)
*year = value;
- /* Handle the month */
+ /* Handle the month (zero based) */
- value = 0; /* zero-based */
- for (;;)
+ min = 0;
+ max = 11;
+
+ do
{
- /* Get the number of days that occurred before the beginning of the next month */
+ /* Get the midpoint */
- tmp = g_daysbeforemonth[value + 1];
- if (value >= 2 && leapyear)
- {
- tmp++;
- }
+ value = (min + max) >> 1;
+
+ /* Get the number of days that occurred before the beginning month
+ * following the midpoint.
+ */
+
+ tmp = clock_daysbeforemonth(value + 1, leapyear);
/* Does that equal or exceed the number of days we have remaining? */
if (tmp >= days)
{
- /* Yes.. this is the one we want. The 'days' for this number of days that
- * occurred before this month.
+ /* Yes.. then the month we want is somewhere between 'min' and the.
+ * midpoint, 'value'. Check if it is the midpoint.
*/
- days -= g_daysbeforemonth[value];
- break;
+ tmp = clock_daysbeforemonth(value, leapyear);
+ if (tmp >= days)
+ {
+ /* No... The one we want is somewhere between min and value-1 */
+
+ max = value - 1;
+ }
+ else
+ {
+ /* Yes.. 'value' contains the month that we want */
+
+ break;
+ }
}
else
{
- /* No... try the next month */
+ /* No... The one we want is somwhere between value+1 and max */
- value++;
+ min = value + 1;
}
}
+ while (min < max);
+
+ /* Subtract the number of days in the selected month */
+
+ days -= clock_daysbeforemonth(value, leapyear);
/* At this point, value has the month into this year (zero based) and days has
* number of days into this month (zero based)
*/
- *month = value;
+ *month = value; /* Zero based */
*day = days + 1; /* 1-based */
}