221 lines
7.5 KiB
C++
221 lines
7.5 KiB
C++
/**
|
|||
|
|
* @file kTimeSpan.cpp
|
||
|
|
*
|
||
|
|
* @internal
|
||
|
|
* Copyright (C) 2008-2021 by LMI Technologies Inc.
|
||
|
|
* Licensed under the MIT License.
|
||
|
|
* Redistributed files must retain the above copyright notice.
|
||
|
|
*/
|
||
|
|
#include <kApi/Utils/kTimeSpan.h>
|
||
|
|
|
||
|
|
#include <kApi/Data/kMath.h>
|
||
|
|
#include <kApi/Io/kSerializer.h>
|
||
|
|
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
/*
|
||
|
|
* kTimeSpanFormat enum
|
||
|
|
*/
|
||
|
|
|
||
|
|
kBeginEnumEx(k, kTimeSpanFormat)
|
||
|
|
kAddEnumerator(kTimeSpanFormat, kTIME_SPAN_FORMAT_PARTS_FULL)
|
||
|
|
kAddEnumerator(kTimeSpanFormat, kTIME_SPAN_FORMAT_PARTS_SIMPLE)
|
||
|
|
kAddEnumerator(kTimeSpanFormat, kTIME_SPAN_FORMAT_HMS_FULL)
|
||
|
|
kAddEnumerator(kTimeSpanFormat, kTIME_SPAN_FORMAT_HMS_SIMPLE)
|
||
|
|
kEndEnumEx()
|
||
|
|
|
||
|
|
/*
|
||
|
|
* kTimeSpan structure
|
||
|
|
*/
|
||
|
|
|
||
|
|
kBeginValueEx(k, kTimeSpan)
|
||
|
|
kAddFlags(kTimeSpan, kTYPE_FLAGS_PRIMITIVE)
|
||
|
|
|
||
|
|
kAddPrivateVersionEx(kTimeSpan, "kdat6", "7.0.0.0", "kTimeSpan-0", Write, Read)
|
||
|
|
|
||
|
|
kAddPrivateVMethod(kTimeSpan, kValue, VEquals)
|
||
|
|
kAddPrivateVMethod(kTimeSpan, kValue, VHashCode)
|
||
|
|
kEndValueEx()
|
||
|
|
|
||
|
|
kFx(kBool) xkTimeSpan_VEquals(kType type, const void* value, const void* other)
|
||
|
|
{
|
||
|
|
return *(kTimeSpan*)value == *(kTimeSpan*)other;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kSize) xkTimeSpan_VHashCode(kType type, const void* value)
|
||
|
|
{
|
||
|
|
return xk64s_VHashCode(kTypeOf(k64s), value);
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_Write(kType type, const void* values, kSize count, kSerializer serializer)
|
||
|
|
{
|
||
|
|
return kSerializer_Write64sArray(serializer, (const k64s*) values, count);
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_Read(kType type, void* values, kSize count, kSerializer serializer)
|
||
|
|
{
|
||
|
|
return kSerializer_Read64sArray(serializer, (k64s*) values, count);
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kTimeSpan_Parts(kTimeSpan span, k32s* daysPart, k32s* hoursPart, k32s* minutesPart, k32s* secondsPart, k32s* microsecondsPart)
|
||
|
|
{
|
||
|
|
if (!kIsNull(daysPart)) *daysPart = kTimeSpan_DaysPart(span);
|
||
|
|
if (!kIsNull(hoursPart)) *hoursPart = kTimeSpan_HoursPart(span);
|
||
|
|
if (!kIsNull(minutesPart)) *minutesPart = kTimeSpan_MinutesPart(span);
|
||
|
|
if (!kIsNull(secondsPart)) *secondsPart = kTimeSpan_SecondsPart(span);
|
||
|
|
if (!kIsNull(microsecondsPart)) *microsecondsPart = kTimeSpan_MicrosecondsPart(span);
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kTimeSpan_Format(kTimeSpan span, kTimeSpanFormat format, kChar* text, kSize capacity)
|
||
|
|
{
|
||
|
|
switch (format)
|
||
|
|
{
|
||
|
|
case kTIME_SPAN_FORMAT_NULL:
|
||
|
|
case kTIME_SPAN_FORMAT_PARTS_FULL:
|
||
|
|
return xkTimeSpan_FormatParts(span, kTRUE, text, capacity);
|
||
|
|
case kTIME_SPAN_FORMAT_PARTS_SIMPLE:
|
||
|
|
return xkTimeSpan_FormatParts(span, kFALSE, text, capacity);
|
||
|
|
case kTIME_SPAN_FORMAT_HMS_FULL:
|
||
|
|
return kStrPrintf(text, capacity, "%lld:%02d:%02d.%06d", kTimeSpan_ToHours64s(span),
|
||
|
|
kTimeSpan_MinutesPart(span), kTimeSpan_SecondsPart(span), kTimeSpan_MicrosecondsPart(span));
|
||
|
|
case kTIME_SPAN_FORMAT_HMS_SIMPLE:
|
||
|
|
return kStrPrintf(text, capacity, "%lld:%02d:%02d", kTimeSpan_ToHours64s(span),
|
||
|
|
kTimeSpan_MinutesPart(span), kTimeSpan_SecondsPart(span));
|
||
|
|
default:
|
||
|
|
return kERROR_PARAMETER;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_FormatParts(kTimeSpan span, kBool includeMicroseconds, kChar* text, kSize capacity)
|
||
|
|
{
|
||
|
|
k32s daysPart, hoursPart, minutesPart, secondsPart, microsecondsPart;
|
||
|
|
kText16 secondsText;
|
||
|
|
|
||
|
|
kCheck(kTimeSpan_Parts(span, &daysPart, &hoursPart, &minutesPart, &secondsPart, µsecondsPart));
|
||
|
|
|
||
|
|
if (includeMicroseconds)
|
||
|
|
{
|
||
|
|
kCheck(kStrPrintf(secondsText, sizeof(secondsText), "%d.%06ds", secondsPart, microsecondsPart));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kCheck(kStrPrintf(secondsText, sizeof(secondsText), "%ds", secondsPart));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (daysPart > 0)
|
||
|
|
{
|
||
|
|
kCheck(kStrPrintf(text, capacity, "%dd %dh %dm %s", daysPart, hoursPart, minutesPart, secondsText));
|
||
|
|
}
|
||
|
|
else if (hoursPart > 0)
|
||
|
|
{
|
||
|
|
kCheck(kStrPrintf(text, capacity, "%dh %dm %s", hoursPart, minutesPart, secondsText));
|
||
|
|
}
|
||
|
|
else if (minutesPart > 0)
|
||
|
|
{
|
||
|
|
kCheck(kStrPrintf(text, capacity, "%dm %s", minutesPart, secondsText));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
kCheck(kStrCopy(text, capacity, secondsText));
|
||
|
|
}
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) kTimeSpan_Parse(kTimeSpan* span, kTimeSpanFormat format, const kChar* text)
|
||
|
|
{
|
||
|
|
switch (format)
|
||
|
|
{
|
||
|
|
case kTIME_SPAN_FORMAT_PARTS_FULL:
|
||
|
|
return xkTimeSpan_ParseFull(span, text);
|
||
|
|
case kTIME_SPAN_FORMAT_PARTS_SIMPLE:
|
||
|
|
return xkTimeSpan_ParseSimple(span, text);
|
||
|
|
case kTIME_SPAN_FORMAT_HMS_FULL:
|
||
|
|
return xkTimeSpan_ParseHmsFull(span, text);
|
||
|
|
case kTIME_SPAN_FORMAT_HMS_SIMPLE:
|
||
|
|
return xkTimeSpan_ParseHmsSimple(span, text);
|
||
|
|
default:
|
||
|
|
//try all known formats, from most detailed to least detailed
|
||
|
|
return (kSuccess(kTimeSpan_Parse(span, kTIME_SPAN_FORMAT_HMS_FULL, text)) ||
|
||
|
|
kSuccess(kTimeSpan_Parse(span, kTIME_SPAN_FORMAT_HMS_SIMPLE, text)) ||
|
||
|
|
kSuccess(kTimeSpan_Parse(span, kTIME_SPAN_FORMAT_PARTS_FULL, text)) ||
|
||
|
|
kSuccess(kTimeSpan_Parse(span, kTIME_SPAN_FORMAT_PARTS_SIMPLE, text))) ? kOK : kERROR_FORMAT;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_ParseFull(kTimeSpan* span, const kChar* text)
|
||
|
|
{
|
||
|
|
k32s daysPart = 0, hoursPart = 0, minutesPart = 0, secondsPart = 0, microsecondsPart = 0;
|
||
|
|
|
||
|
|
if (sscanf(text, "%dd %dh %dm %d.%06ds", &daysPart, &hoursPart, &minutesPart, &secondsPart, µsecondsPart) != 5)
|
||
|
|
{
|
||
|
|
daysPart = 0;
|
||
|
|
|
||
|
|
if (sscanf(text, "%dh %dm %d.%06ds", &hoursPart, &minutesPart, &secondsPart, µsecondsPart) != 4)
|
||
|
|
{
|
||
|
|
hoursPart = 0;
|
||
|
|
|
||
|
|
if (sscanf(text, "%dm %d.%06ds", &minutesPart, &secondsPart, µsecondsPart) != 3)
|
||
|
|
{
|
||
|
|
minutesPart = 0;
|
||
|
|
|
||
|
|
kCheckTrue(sscanf(text, "%d.%06ds", &secondsPart, µsecondsPart) == 2, kERROR_FORMAT);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
*span = kTimeSpan_FromParts(daysPart, hoursPart, minutesPart, secondsPart, microsecondsPart);
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_ParseSimple(kTimeSpan* span, const kChar* text)
|
||
|
|
{
|
||
|
|
k32s daysPart = 0, hoursPart = 0, minutesPart = 0, secondsPart = 0;
|
||
|
|
|
||
|
|
if (sscanf(text, "%dd %dh %dm %ds", &daysPart, &hoursPart, &minutesPart, &secondsPart) != 4)
|
||
|
|
{
|
||
|
|
daysPart = 0;
|
||
|
|
|
||
|
|
if (sscanf(text, "%dh %dm %ds", &hoursPart, &minutesPart, &secondsPart) != 3)
|
||
|
|
{
|
||
|
|
hoursPart = 0;
|
||
|
|
|
||
|
|
if (sscanf(text, "%dm %ds", &minutesPart, &secondsPart) != 2)
|
||
|
|
{
|
||
|
|
minutesPart = 0;
|
||
|
|
|
||
|
|
kCheckTrue(sscanf(text, "%ds", &secondsPart) == 1, kERROR_FORMAT);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
*span = kTimeSpan_FromParts(daysPart, hoursPart, minutesPart, secondsPart, 0);
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_ParseHmsFull(kTimeSpan* span, const kChar* text)
|
||
|
|
{
|
||
|
|
k32s daysPart = 0, hoursPart = 0, minutesPart = 0, secondsPart = 0, microsecondsPart = 0;
|
||
|
|
|
||
|
|
kCheckTrue(sscanf(text, "%d:%02d:%02d.%06d", &hoursPart, &minutesPart, &secondsPart, µsecondsPart) == 4, kERROR_FORMAT);
|
||
|
|
|
||
|
|
*span = kTimeSpan_FromParts(daysPart, hoursPart, minutesPart, secondsPart, microsecondsPart);
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|
||
|
|
|
||
|
|
kFx(kStatus) xkTimeSpan_ParseHmsSimple(kTimeSpan* span, const kChar* text)
|
||
|
|
{
|
||
|
|
k32s daysPart = 0, hoursPart = 0, minutesPart = 0, secondsPart = 0;
|
||
|
|
|
||
|
|
kCheckTrue(sscanf(text, "%d:%02d:%02d", &hoursPart, &minutesPart, &secondsPart) == 3, kERROR_FORMAT);
|
||
|
|
|
||
|
|
*span = kTimeSpan_FromParts(daysPart, hoursPart, minutesPart, secondsPart, 0);
|
||
|
|
|
||
|
|
return kOK;
|
||
|
|
}
|