- wxCopyFile() respects the file permissions (Roland Scholz)
- wxFTP::GetFileSize() added (Søren Erland Vestø)
- wxDateTime::IsSameDate() bug fixed
+- wxTimeSpan::Format() now behaves more as expected, see docs
All (GUI):
};
\end{verbatim}
-Differnet parst of the world use different conventions for the week start.
+Different parst of the world use different conventions for the week start.
In some countries, the week starts on Sunday, while in others - on Monday.
The ISO standard doesn't address this issue, so we support both conventions in
the functions whose result depends on it (\helpref{GetWeekOfYear}{wxdatetimegetweekofyear} and
\wxheading{See also}
\helpref{Date classes overview}{wxdatetimeoverview},\rtfsp
-wxTimeSpan,\rtfsp
-wxDateSpan,\rtfsp
+\helpref{wxTimeSpan}{wxtimespan},\rtfsp
+\helpref{wxDateSpan}{wxdatespan},\rtfsp
\helpref{wxCalendarCtrl}{wxcalendarctrl}
\latexignore{\rtfignore{\wxheading{Function groups}}}
\section{\class{wxTimeSpan}}\label{wxtimespan}
-TODO
+wxTimeSpan class represents a time interval.
+
+\wxheading{Derived from}
+
+No base class
+
+\wxheading{Include files}
+
+<wx/datetime.h>
+
+\wxheading{See also}
+
+\helpref{Date classes overview}{wxdatetimeoverview},\rtfsp
+\helpref{wxDateTime}{wxdatetime}
+
+\latexignore{\rtfignore{\wxheading{Function groups}}}
+
+\membersection{Static functions}
+
+\membersection{Constructors}
+
+\helpref{wxTimeSpan()}{wxtimespandef}
+\helpref{wxTimeSpan(hours, min, sec, msec)}{wxtimespan}
+
+\membersection{Accessors}
+
+\membersection{Operations}
+
+\membersection{Tests}
+
+\membersection{Formatting time spans}
+
+\helpref{Format}{wxtimespanformat}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Start of member function part %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\helponly{\insertatlevel{2}{
+ \wxheading{Members}
+}}
+
+\membersection{wxTimeSpan::Format}\label{wxtimespanformat}
+
+\func{wxString}{Format}{\param{const wxChar * }{format = "\%H:\%M:\%S"}}
+
+Returns the string containing the formatted representation of the time span.
+The following format specifiers are allowed after \%:
+
+\twocolwidtha{5cm}%
+\begin{twocollist}\itemsep=0pt
+\twocolitem{H}{number of {\bf H}ours}
+\twocolitem{M}{number of {\bf M}inutes}
+\twocolitem{S}{number of {\bf S}econds}
+\twocolitem{l}{number of mi{\bf l}liseconds}
+\twocolitem{D}{number of {\bf D}ays}
+\twocolitem{E}{number of w{\bf E}eks}
+\twocolitem{\%}{the percent character}
+\end{twocollist}
+
+Note that, for example, the number of hours in the description above is not
+well defined: it can be either the total number of hours (for example, for a
+time span of $50$ hours this would be $50$) or just the hour part of the time
+span, which would be $2$ in this case as $50$ hours is equal to $2$ days and
+$2$ hours.
+
+wxTimeSpan resolves this ambiguity in the following way: if there had been,
+indeed, the {\tt \%D} format specified preceding the {\tt \%H}, then it is
+interpreted as $2$. Otherwise, it is $50$.
+
+The same applies to all other format specifiers: if they follow a specifier of
+larger unit, only the rest part is taken, otherwise the full value is used.
//#define TEST_ARRAYS
//#define TEST_CMDLINE
-//#define TEST_DATETIME
+#define TEST_DATETIME
//#define TEST_DIR
//#define TEST_DLLLOADER
//#define TEST_ENVIRON
puts("");
}
+static void TestTimeSpanFormat()
+{
+ puts("\n*** wxTimeSpan tests ***");
+
+ static const char *formats[] =
+ {
+ _T("(default) %H:%M:%S"),
+ _T("%E weeks and %D days"),
+ _T("%l milliseconds"),
+ _T("(with ms) %H:%M:%S:%l"),
+ _T("100%% of minutes is %M"), // test "%%"
+ _T("%D days and %H hours"),
+ };
+
+ wxTimeSpan ts1(1, 2, 3, 4),
+ ts2(111, 222, 333);
+ for ( size_t n = 0; n < WXSIZEOF(formats); n++ )
+ {
+ printf("ts1 = %s\tts2 = %s\n",
+ ts1.Format(formats[n]).c_str(),
+ ts2.Format(formats[n]).c_str());
+ }
+
+ puts("");
+}
+
#if 0
// test compatibility with the old wxDate/wxTime classes
#endif // TEST_TIMER
#ifdef TEST_DATETIME
- if ( 1 )
+ if ( 0 )
{
TestTimeSet();
TestTimeStatic();
TestTimeZoneBug();
}
+ TestTimeSpanFormat();
if ( 0 )
TestDateTimeInteractive();
#endif // TEST_DATETIME
// some trivial ones
static const int MONTHS_IN_YEAR = 12;
-static const int SECONDS_IN_MINUTE = 60;
+static const int SEC_PER_MIN = 60;
+
+static const int MIN_PER_HOUR = 60;
+
+static const int HOURS_PER_DAY = 24;
static const long SECONDS_PER_DAY = 86400l;
+static const int DAYS_PER_WEEK = 7;
+
static const long MILLISECONDS_PER_DAY = 86400000l;
// this is the integral part of JDN of the midnight of Jan 1, 1970
wxString str;
str.Alloc(wxStrlen(format));
+ // Suppose we have wxTimeSpan ts(1 /* hour */, 2 /* min */, 3 /* sec */)
+ //
+ // Then, of course, ts.Format("%H:%M:%S") must return "01:02:03", but the
+ // question is what should ts.Format("%S") do? The code here returns "3273"
+ // in this case (i.e. the total number of seconds, not just seconds % 60)
+ // because, for me, this call means "give me entire time interval in
+ // seconds" and not "give me the seconds part of the time interval"
+ //
+ // If we agree that it should behave like this, it is clear that the
+ // interpretation of each format specifier depends on the presence of the
+ // other format specs in the string: if there was "%H" before "%M", we
+ // should use GetMinutes() % 60, otherwise just GetMinutes() &c
+
+ // we remember the most important unit found so far
+ enum TimeSpanPart
+ {
+ Part_Week,
+ Part_Day,
+ Part_Hour,
+ Part_Min,
+ Part_Sec,
+ Part_MSec
+ } partBiggest = Part_MSec;
+
for ( const wxChar *pch = format; *pch; pch++ )
{
wxChar ch = *pch;
if ( ch == _T('%') )
{
- wxString tmp;
+ // the start of the format specification of the printf() below
+ wxString fmtPrefix = _T('%');
+
+ // the number
+ long n;
ch = *++pch; // get the format spec char
switch ( ch )
// fall through
case _T('%'):
- // will get to str << ch below
- break;
+ str += ch;
+
+ // skip the part below switch
+ continue;
case _T('D'):
- tmp.Printf(_T("%d"), GetDays());
+ n = GetDays();
+ if ( partBiggest < Part_Day )
+ {
+ n %= DAYS_PER_WEEK;
+ }
+ else
+ {
+ partBiggest = Part_Day;
+ }
break;
case _T('E'):
- tmp.Printf(_T("%d"), GetWeeks());
+ partBiggest = Part_Week;
+ n = GetWeeks();
break;
case _T('H'):
- tmp.Printf(_T("%02d"), GetHours());
+ n = GetHours();
+ if ( partBiggest < Part_Hour )
+ {
+ n %= HOURS_PER_DAY;
+ }
+ else
+ {
+ partBiggest = Part_Hour;
+ }
+
+ fmtPrefix += _T("02");
break;
case _T('l'):
- tmp.Printf(_T("%03ld"), GetMilliseconds().ToLong());
+ n = GetMilliseconds().ToLong();
+ if ( partBiggest < Part_MSec )
+ {
+ n %= 1000;
+ }
+ //else: no need to reset partBiggest to Part_MSec, it is
+ // the least significant one anyhow
+
+ fmtPrefix += _T("03");
break;
case _T('M'):
- tmp.Printf(_T("%02d"), GetMinutes());
+ n = GetMinutes();
+ if ( partBiggest < Part_Min )
+ {
+ n %= MIN_PER_HOUR;
+ }
+ else
+ {
+ partBiggest = Part_Min;
+ }
+
+ fmtPrefix += _T("02");
break;
case _T('S'):
- tmp.Printf(_T("%02ld"), GetSeconds().ToLong());
+ n = GetSeconds().ToLong();
+ if ( partBiggest < Part_Sec )
+ {
+ n %= SEC_PER_MIN;
+ }
+ else
+ {
+ partBiggest = Part_Sec;
+ }
+
+ fmtPrefix += _T("02");
break;
}
- if ( !!tmp )
- {
- str += tmp;
-
- // skip str += ch below
- continue;
- }
+ str += wxString::Format(fmtPrefix + _T("ld"), n);
+ }
+ else
+ {
+ // normal character, just copy
+ str += ch;
}
-
- str += ch;
}
return str;