Skip to content

Commit 7fc5f88

Browse files
committed
Fix nasa#2316, Re-introduce change from PR nasa#2356.
1 parent 600a209 commit 7fc5f88

File tree

6 files changed

+49
-167
lines changed

6 files changed

+49
-167
lines changed

Diff for: modules/core_api/fsw/inc/cfe_time.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,8 @@ CFE_Status_t CFE_TIME_UnregisterSynchCallback(CFE_TIME_SynchCallbackPtr_t Callba
691691
** - \c \\0 = trailing null
692692
**
693693
** \par Assumptions, External Events, and Notes:
694+
** - This function calls strftime to format the output. Systems without this
695+
** C99-standard function will have to write their own implementation.
694696
** - The value of the time argument is simply added to the configuration
695697
** definitions for the ground epoch and converted into a fixed length
696698
** string in the buffer provided by the caller.
@@ -706,8 +708,12 @@ CFE_Status_t CFE_TIME_UnregisterSynchCallback(CFE_TIME_SynchCallbackPtr_t Callba
706708
**
707709
** \param[in] TimeToPrint The time to print into the character array.
708710
**
711+
** \return Execution status, see \ref CFEReturnCodes
712+
** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS
713+
** \retval #CFE_TIME_BAD_ARGUMENT \copybrief CFE_TIME_BAD_ARGUMENT
714+
**
709715
******************************************************************************/
710-
void CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint);
716+
CFE_Status_t CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint);
711717

712718
/*****************************************************************************/
713719
/**

Diff for: modules/core_api/ut-stubs/src/cfe_time_handlers.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@
4545
* Default handler for CFE_TIME_Print coverage stub function
4646
*
4747
*------------------------------------------------------------*/
48-
void UT_DefaultHandler_CFE_TIME_Print(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context)
48+
CFE_Status_t UT_DefaultHandler_CFE_TIME_Print(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context)
4949
{
5050
char * PrintBuffer = UT_Hook_GetArgValueByName(Context, "PrintBuffer", char *);
5151
CFE_TIME_SysTime_t TimeToPrint = UT_Hook_GetArgValueByName(Context, "TimeToPrint", CFE_TIME_SysTime_t);
5252

5353
snprintf(PrintBuffer, CFE_TIME_PRINTED_STRING_SIZE, "UT %u.%u -", (unsigned int)TimeToPrint.Seconds,
5454
(unsigned int)TimeToPrint.Subseconds);
55+
return CFE_SUCCESS;
5556
}
5657

5758
/*------------------------------------------------------------

Diff for: modules/core_api/ut-stubs/src/cfe_time_stubs.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,16 @@ uint32 CFE_TIME_Micro2SubSecs(uint32 MicroSeconds)
305305
* Generated stub function for CFE_TIME_Print()
306306
* ----------------------------------------------------
307307
*/
308-
void CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint)
308+
CFE_Status_t CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint)
309309
{
310+
UT_GenStub_SetupReturnBuffer(CFE_TIME_Print, CFE_Status_t);
311+
310312
UT_GenStub_AddParam(CFE_TIME_Print, char *, PrintBuffer);
311313
UT_GenStub_AddParam(CFE_TIME_Print, CFE_TIME_SysTime_t, TimeToPrint);
312314

313315
UT_GenStub_Execute(CFE_TIME_Print, Basic, UT_DefaultHandler_CFE_TIME_Print);
316+
317+
return UT_GenStub_GetReturnValue(CFE_TIME_Print, CFE_Status_t);
314318
}
315319

316320
/*

Diff for: modules/time/config/default_cfe_time_interface_cfg.h

+3-12
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,14 @@
151151
** \cfetimecfg Default EPOCH Values
152152
**
153153
** \par Description:
154-
** Default ground time epoch values
154+
** Default ground time epoch values (from Jan. 1, 1970 00:00:00)
155155
** Note: these values are used only by the CFE_TIME_Print() API function
156156
**
157157
** \par Limits
158-
** Year - must be within 136 years
159-
** Day - Jan 1 = 1, Feb 1 = 32, etc.
160-
** Hour - 0 to 23
161-
** Minute - 0 to 59
162-
** Second - 0 to 59
163158
** Micros - 0 to 999999
164159
*/
165-
#define CFE_MISSION_TIME_EPOCH_YEAR 1980
166-
#define CFE_MISSION_TIME_EPOCH_DAY 1
167-
#define CFE_MISSION_TIME_EPOCH_HOUR 0
168-
#define CFE_MISSION_TIME_EPOCH_MINUTE 0
169-
#define CFE_MISSION_TIME_EPOCH_SECOND 0
170-
#define CFE_MISSION_TIME_EPOCH_MICROS 0
160+
#define CFE_MISSION_TIME_EPOCH_SECONDS 315532800 /* Jan. 1, 1980 00:00:00 */
161+
#define CFE_MISSION_TIME_EPOCH_MICROS 0
171162

172163
/**
173164
** \cfetimecfg Time File System Factor

Diff for: modules/time/fsw/src/cfe_time_api.c

+20-138
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
#include <string.h>
3636

37+
#include <time.h>
38+
3739
/*----------------------------------------------------------------
3840
*
3941
* Implemented per public API
@@ -563,150 +565,30 @@ uint32 CFE_TIME_Micro2SubSecs(uint32 MicroSeconds)
563565
* See description in header file for argument/return detail
564566
*
565567
*-----------------------------------------------------------------*/
566-
void CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint)
568+
CFE_Status_t CFE_TIME_Print(char *PrintBuffer, CFE_TIME_SysTime_t TimeToPrint)
567569
{
568-
uint32 NumberOfYears;
569-
uint32 NumberOfDays;
570-
uint32 NumberOfHours;
571-
uint32 NumberOfMinutes;
572-
uint32 NumberOfSeconds;
573-
uint32 NumberOfMicros;
574-
uint32 DaysInThisYear;
575-
576-
bool StillCountingYears = true;
570+
size_t FmtLen = 0;
571+
uint32 Micros = (CFE_TIME_Sub2MicroSecs(TimeToPrint.Subseconds) + CFE_MISSION_TIME_EPOCH_MICROS) / 10;
572+
struct tm tm;
577573

578574
if (PrintBuffer == NULL)
579575
{
580-
CFE_ES_WriteToSysLog("%s: Failed invalid arguments\n", __func__);
581-
return;
582-
}
583-
584-
/*
585-
** Convert the cFE time (offset from epoch) into calendar time...
586-
*/
587-
NumberOfMicros = CFE_TIME_Sub2MicroSecs(TimeToPrint.Subseconds) + CFE_MISSION_TIME_EPOCH_MICROS;
588-
589-
NumberOfMinutes = (NumberOfMicros / 60000000) + (TimeToPrint.Seconds / 60) + CFE_MISSION_TIME_EPOCH_MINUTE;
590-
NumberOfMicros = NumberOfMicros % 60000000;
591-
592-
NumberOfSeconds = (NumberOfMicros / 1000000) + (TimeToPrint.Seconds % 60) + CFE_MISSION_TIME_EPOCH_SECOND;
593-
NumberOfMicros = NumberOfMicros % 1000000;
594-
/*
595-
** Adding the epoch "seconds" after computing the minutes avoids
596-
** overflow problems when the input time value (seconds) is
597-
** at, or near, 0xFFFFFFFF...
598-
*/
599-
while (NumberOfSeconds >= 60)
600-
{
601-
NumberOfMinutes++;
602-
NumberOfSeconds -= 60;
603-
}
604-
605-
/*
606-
** Compute the years/days/hours/minutes...
607-
*/
608-
NumberOfHours = (NumberOfMinutes / 60) + CFE_MISSION_TIME_EPOCH_HOUR;
609-
NumberOfMinutes = (NumberOfMinutes % 60);
610-
611-
/*
612-
** Unlike hours and minutes, epoch days are counted as Jan 1 = day 1...
613-
*/
614-
NumberOfDays = (NumberOfHours / 24) + (CFE_MISSION_TIME_EPOCH_DAY - 1);
615-
NumberOfHours = (NumberOfHours % 24);
616-
617-
NumberOfYears = CFE_MISSION_TIME_EPOCH_YEAR;
618-
619-
/*
620-
** Convert total number of days into years and remainder days...
621-
*/
622-
while (StillCountingYears)
623-
{
624-
/*
625-
** Set number of days in this year (leap year?)...
626-
*/
627-
DaysInThisYear = 365;
628-
629-
if ((NumberOfYears % 4) == 0)
630-
{
631-
if ((NumberOfYears % 100) != 0)
632-
{
633-
DaysInThisYear = 366;
634-
}
635-
else if ((NumberOfYears % 400) == 0)
636-
{
637-
DaysInThisYear = 366;
638-
}
639-
else
640-
{
641-
/* Do Nothing. Non-leap year. */
642-
}
643-
}
644-
645-
/*
646-
** When we have less than a years worth of days, we're done...
647-
*/
648-
if (NumberOfDays < DaysInThisYear)
649-
{
650-
StillCountingYears = false;
651-
}
652-
else
653-
{
654-
/*
655-
** Add a year and remove the number of days in that year...
656-
*/
657-
NumberOfYears++;
658-
NumberOfDays -= DaysInThisYear;
659-
}
576+
return CFE_TIME_BAD_ARGUMENT;
660577
}
661578

662-
/*
663-
** Unlike hours and minutes, days are displayed as Jan 1 = day 1...
664-
*/
665-
NumberOfDays++;
666-
667-
/*
668-
** After computing microseconds, convert to 5 digits from 6 digits...
669-
*/
670-
NumberOfMicros = NumberOfMicros / 10;
671-
672-
/*
673-
** Build formatted output string (yyyy-ddd-hh:mm:ss.xxxxx)...
674-
*/
675-
*PrintBuffer++ = '0' + (char)(NumberOfYears / 1000);
676-
NumberOfYears = NumberOfYears % 1000;
677-
*PrintBuffer++ = '0' + (char)(NumberOfYears / 100);
678-
NumberOfYears = NumberOfYears % 100;
679-
*PrintBuffer++ = '0' + (char)(NumberOfYears / 10);
680-
*PrintBuffer++ = '0' + (char)(NumberOfYears % 10);
681-
*PrintBuffer++ = '-';
682-
683-
*PrintBuffer++ = '0' + (char)(NumberOfDays / 100);
684-
NumberOfDays = NumberOfDays % 100;
685-
*PrintBuffer++ = '0' + (char)(NumberOfDays / 10);
686-
*PrintBuffer++ = '0' + (char)(NumberOfDays % 10);
687-
*PrintBuffer++ = '-';
688-
689-
*PrintBuffer++ = '0' + (char)(NumberOfHours / 10);
690-
*PrintBuffer++ = '0' + (char)(NumberOfHours % 10);
691-
*PrintBuffer++ = ':';
692-
693-
*PrintBuffer++ = '0' + (char)(NumberOfMinutes / 10);
694-
*PrintBuffer++ = '0' + (char)(NumberOfMinutes % 10);
695-
*PrintBuffer++ = ':';
696-
697-
*PrintBuffer++ = '0' + (char)(NumberOfSeconds / 10);
698-
*PrintBuffer++ = '0' + (char)(NumberOfSeconds % 10);
699-
*PrintBuffer++ = '.';
700-
701-
*PrintBuffer++ = '0' + (char)(NumberOfMicros / 10000);
702-
NumberOfMicros = NumberOfMicros % 10000;
703-
*PrintBuffer++ = '0' + (char)(NumberOfMicros / 1000);
704-
NumberOfMicros = NumberOfMicros % 1000;
705-
*PrintBuffer++ = '0' + (char)(NumberOfMicros / 100);
706-
NumberOfMicros = NumberOfMicros % 100;
707-
*PrintBuffer++ = '0' + (char)(NumberOfMicros / 10);
708-
*PrintBuffer++ = '0' + (char)(NumberOfMicros % 10);
709-
*PrintBuffer++ = '\0';
579+
time_t sec = TimeToPrint.Seconds + CFE_MISSION_TIME_EPOCH_SECONDS; // epoch is Jan 1, 1980
580+
gmtime_r(&sec, &tm);
581+
FmtLen = strftime(PrintBuffer, CFE_TIME_PRINTED_STRING_SIZE - 6, "%Y-%j-%H:%M:%S", &tm);
582+
PrintBuffer += FmtLen;
583+
*(PrintBuffer++) = '.';
584+
585+
*(PrintBuffer++) = '0' + (char)((Micros % 100000) / 10000);
586+
*(PrintBuffer++) = '0' + (char)((Micros % 10000) / 1000);
587+
*(PrintBuffer++) = '0' + (char)((Micros % 1000) / 100);
588+
*(PrintBuffer++) = '0' + (char)((Micros % 100) / 10);
589+
*(PrintBuffer++) = '0' + (char)(Micros % 10);
590+
*PrintBuffer = '\0';
591+
return CFE_SUCCESS;
710592
}
711593

712594
/*----------------------------------------------------------------

Diff for: modules/time/ut-coverage/time_UT.c

+12-14
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ void Test_ConvertTime(void)
821821
**
822822
** NOTE: Test results depend on the epoch values in cfe_mission_cfg.h (the
823823
** tests below assume an epoch of 1980-001-00:00:00.00000). Full
824-
** coverage is possible only when CFE_MISSION_TIME_EPOCH_SECOND > 0
824+
** coverage is possible only when CFE_MISSION_TIME_EPOCH_SECONDS > 0
825825
*/
826826
void Test_Print(void)
827827
{
@@ -834,20 +834,18 @@ void Test_Print(void)
834834

835835
UtPrintf("Begin Test Print");
836836

837-
if (CFE_MISSION_TIME_EPOCH_YEAR != 1980 || CFE_MISSION_TIME_EPOCH_DAY != 1 || CFE_MISSION_TIME_EPOCH_HOUR != 0 ||
838-
CFE_MISSION_TIME_EPOCH_MINUTE != 0 || CFE_MISSION_TIME_EPOCH_SECOND != 0 || CFE_MISSION_TIME_EPOCH_MICROS != 0)
837+
if (CFE_MISSION_TIME_EPOCH_SECONDS != 0 || CFE_MISSION_TIME_EPOCH_MICROS != 0)
839838
{
840839
UtPrintf("Custom epoch time requires manual inspection for CFE_TIME_Print");
841840
usingDefaultEpoch = false;
842841
}
843842

844843
/* Test print with null print buffer argument */
845844
UT_InitData();
846-
UtAssert_VOIDCALL(CFE_TIME_Print(NULL, time));
847-
CFE_UtAssert_SYSLOG(TIME_SYSLOG_MSGS[6]);
845+
UtAssert_INT32_EQ(CFE_TIME_Print(NULL, time), CFE_TIME_BAD_ARGUMENT);
848846

849847
/* Test with zero time value */
850-
CFE_TIME_Print(timeBuf, time);
848+
CFE_UtAssert_SUCCESS(CFE_TIME_Print(timeBuf, time));
851849
if (usingDefaultEpoch)
852850
{
853851
strcpy(expectedBuf, "1980-001-00:00:00.00000");
@@ -860,12 +858,12 @@ void Test_Print(void)
860858
}
861859

862860
/* Test with a time value that causes seconds >= 60 when
863-
* CFE_MISSION_TIME_EPOCH_SECOND > 0
861+
* CFE_MISSION_TIME_EPOCH_SECONDS > 0
864862
*/
865863
time.Subseconds = 0;
866864
time.Seconds = 59;
867865

868-
CFE_TIME_Print(timeBuf, time);
866+
CFE_UtAssert_SUCCESS(CFE_TIME_Print(timeBuf, time));
869867
if (usingDefaultEpoch)
870868
{
871869
strcpy(expectedBuf, "1980-001-00:00:59.00000");
@@ -881,7 +879,7 @@ void Test_Print(void)
881879
time.Subseconds = 215000;
882880
time.Seconds = 1041472984;
883881

884-
CFE_TIME_Print(timeBuf, time);
882+
CFE_UtAssert_SUCCESS(CFE_TIME_Print(timeBuf, time));
885883
if (usingDefaultEpoch)
886884
{
887885
strcpy(expectedBuf, "2013-001-02:03:04.00005");
@@ -893,14 +891,14 @@ void Test_Print(void)
893891
(unsigned int)time.Seconds, (unsigned int)time.Subseconds, timeBuf);
894892
}
895893

896-
/* Test with maximum seconds and subseconds values */
897-
time.Subseconds = 0xffffffff;
898-
time.Seconds = 0xffffffff;
894+
/* Test with sufficiently-large seconds and subseconds values */
895+
time.Subseconds = 0x7fffffff;
896+
time.Seconds = 0x7fffffff;
899897

900-
CFE_TIME_Print(timeBuf, time);
898+
CFE_UtAssert_SUCCESS(CFE_TIME_Print(timeBuf, time));
901899
if (usingDefaultEpoch)
902900
{
903-
strcpy(expectedBuf, "2116-038-06:28:15.99999");
901+
strcpy(expectedBuf, "2048-019-03:14:07.49999");
904902
UtAssert_STRINGBUF_EQ(timeBuf, sizeof(timeBuf), expectedBuf, sizeof(expectedBuf));
905903
}
906904
else

0 commit comments

Comments
 (0)