14 #include <qdatetime.h> 20 static const double msecs[] =
26 24.0 * 3600.0 * 1000.0,
27 7.0 * 24.0 * 3600.0 * 1000.0,
28 30.0 * 24.0 * 3600.0 * 1000.0,
29 365.0 * 24.0 * 3600.0 * 1000.0,
39 double value,
double stepSize,
bool up )
41 double d = value / stepSize;
42 d = up ? std::ceil( d ) : std::floor( d );
44 return static_cast< int >( d * stepSize );
50 switch( intervalType )
54 const double secsTo = minDate.secsTo( maxDate );
55 const double msecs = maxDate.time().msec() -
56 minDate.time().msec();
58 return secsTo * 1000 + msecs;
62 return minDate.secsTo( maxDate );
66 const double secsTo = minDate.secsTo( maxDate );
67 return std::floor( secsTo / 60 );
71 const double secsTo = minDate.secsTo( maxDate );
72 return std::floor( secsTo / 3600 );
76 return minDate.daysTo( maxDate );
80 return std::floor( minDate.daysTo( maxDate ) / 7.0 );
85 double( maxDate.date().year() ) - minDate.date().year();
87 int months = maxDate.date().month() - minDate.date().month();
88 if ( maxDate.date().day() < minDate.date().day() )
91 return years * 12 + months;
96 double( maxDate.date().year() ) - minDate.date().year();
98 if ( maxDate.date().month() < minDate.date().month() )
109 const QDateTime& minDate,
const QDateTime& maxDate,
113 const QDateTime maxD =
QwtDate::ceil( maxDate, intervalType );
119 const int limits[],
size_t numLimits )
121 for ( uint i = 0; i < numLimits; i++ )
123 const int numSteps = intervalSize / limits[ i ];
125 if ( numSteps > 1 && numSteps <= maxSteps &&
126 numSteps * limits[ i ] == intervalSize )
135 static int qwtStepSize(
int intervalSize,
int maxSteps, uint base )
142 for (
int numSteps = maxSteps; numSteps > 1; numSteps-- )
144 const double stepSize = double( intervalSize ) / numSteps;
146 const double p = std::floor( std::log( stepSize ) / std::log(
double( base ) ) );
147 const double fraction = std::pow( base, p );
149 for ( uint n = base; n >= 1; n /= 2 )
151 if ( qFuzzyCompare( stepSize, n * fraction ) )
152 return qRound( stepSize );
154 if ( n == 3 && ( base % 2 ) == 0 )
156 if ( qFuzzyCompare( stepSize, 2 * fraction ) )
157 return qRound( stepSize );
167 const int limits[],
size_t numLimits )
169 const int v =
qwtCeil( intervalSize /
double( numSteps ) );
171 for ( uint i = 0; i < numLimits - 1; i++ )
173 if ( v <= limits[i] )
177 return limits[ numLimits - 1 ];
185 if ( ( intervalSize > numSteps ) &&
186 ( intervalSize <= 2 * numSteps ) )
194 switch( intervalType )
199 static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 };
202 limits,
sizeof( limits ) /
sizeof(
int ) );
208 static int limits[] = { 1, 2, 3, 4, 6, 12, 24 };
211 limits,
sizeof( limits ) /
sizeof(
int ) );
217 const double v = intervalSize / double( numSteps );
219 stepSize = std::ceil( v );
221 stepSize = std::ceil( v / 7 ) * 7;
227 static int limits[] = { 1, 2, 4, 8, 12, 26, 52 };
230 limits,
sizeof( limits ) /
sizeof(
int ) );
236 static int limits[] = { 1, 2, 3, 4, 6, 12 };
239 limits,
sizeof( limits ) /
sizeof(
int ) );
248 intervalSize, numSteps, 10 );
258 double minStepSize = 0.0;
260 switch( intervalType )
264 minStepSize =
qwtStepSize( stepSize, maxMinSteps, 10 );
265 if ( minStepSize == 0.0 )
266 minStepSize = 0.5 * stepSize;
272 static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 };
276 if ( stepSize > maxMinSteps )
279 limits,
sizeof( limits ) /
sizeof(
int ) );
285 limits,
sizeof( limits ) /
sizeof(
int ) );
289 minStepSize = stepSize / numSteps;
297 if ( stepSize > maxMinSteps )
299 static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 };
302 limits,
sizeof( limits ) /
sizeof(
int ) );
306 static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 };
309 limits,
sizeof( limits ) /
sizeof(
int ) );
313 minStepSize = stepSize / numSteps;
321 if ( stepSize > maxMinSteps )
323 static int limits[] = { 1, 2, 3, 7, 14, 28 };
326 limits,
sizeof( limits ) /
sizeof(
int ) );
330 static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 };
333 limits,
sizeof( limits ) /
sizeof(
int ) );
337 minStepSize = stepSize / numSteps;
343 const int daysInStep = stepSize * 7;
345 if ( maxMinSteps >= daysInStep )
348 minStepSize = 1.0 / 7.0;
355 const int stepSizeInWeeks = stepSize;
357 if ( stepSizeInWeeks <= maxMinSteps )
364 stepSizeInWeeks, maxMinSteps, 10 );
373 if ( stepSize < maxMinSteps )
374 maxMinSteps =
static_cast< int >( stepSize );
376 static int limits[] = { 1, 2, 3, 4, 6, 12 };
379 limits,
sizeof( limits ) /
sizeof(
int ) );
382 minStepSize = stepSize / numSteps;
388 if ( stepSize >= maxMinSteps )
391 stepSize, maxMinSteps, 10 );
397 static int limits[] = { 1, 2, 3, 4, 6, 12 };
399 int numSteps =
qwtStepCount( 12 * stepSize, maxMinSteps,
400 limits,
sizeof( limits ) /
sizeof(
int ) );
403 minStepSize = stepSize / numSteps;
413 && minStepSize == 0.0 )
415 minStepSize = 0.5 * stepSize;
422 int secondsMajor,
int secondsMinor )
424 if ( secondsMinor <= 0 )
427 QDateTime minDate = dateTime.addSecs( -secondsMajor );
435 while ( minDate < dateTime &&
438 minDate = minDate.addSecs( 3600 );
439 dstMin += 3600 * 1000.0;
443 ticks.reserve( 3600 / secondsMinor);
445 for (
int i = 0; i < 3600; i += secondsMinor )
446 ticks += dstMin + i * 1000.0;
452 const QDateTime& minDate,
const QDateTime& maxDate,
453 double stepSize,
int maxMinSteps,
457 double minStepSize = 0;
459 if ( maxMinSteps > 1 )
462 maxMinSteps, intervalType );
465 bool daylightSaving =
false;
466 if ( minDate.timeSpec() == Qt::LocalTime )
469 if ( intervalType == QwtDate::Hour )
471 daylightSaving = stepSize > 1;
476 const int secondsMajor =
static_cast< int >( stepSize * s );
477 const double secondsMinor = minStepSize * s;
490 for ( QDateTime dt = minDate; dt <= maxDate;
491 dt = dt.addSecs( secondsMajor ) )
498 if ( daylightSaving )
501 majorValue += offset * 1000.0;
503 if ( offset > dstOff )
508 dt, secondsMajor, qRound( secondsMinor ) );
514 if ( majorTicks.isEmpty() || majorTicks.last() != majorValue )
515 majorTicks += majorValue;
517 if ( secondsMinor > 0.0 )
519 const int numMinorSteps =
qwtFloor( secondsMajor / secondsMinor );
521 for (
int i = 1; i < numMinorSteps; i++ )
523 const QDateTime mt = dt.addMSecs(
524 qRound64( i * secondsMinor * 1000 ) );
527 if ( daylightSaving )
530 minorValue += offset * 1000.0;
533 if ( minorTicks.isEmpty() || minorTicks.last() != minorValue )
535 const bool isMedium = ( numMinorSteps % 2 == 0 )
536 && ( i != 1 ) && ( i == numMinorSteps / 2 );
539 mediumTicks += minorValue;
541 minorTicks += minorValue;
560 QDateTime& minDate,
const QDateTime& maxDate,
561 double stepSize,
int maxMinSteps )
568 int minStepSize = 0.0;
570 if ( maxMinSteps > 1 )
574 if ( maxMinSteps >= 30 )
576 else if ( maxMinSteps >= 6 )
578 else if ( maxMinSteps >= 3 )
594 for ( QDateTime dt = minDate;
595 dt <= maxDate; dt = dt.addMonths( stepSize ) )
602 if ( minStepDays > 0 )
604 for (
int days = minStepDays;
605 days < 30; days += minStepDays )
609 if ( days == 15 && minStepDays != 15 )
615 else if ( minStepSize > 0.0 )
617 const int numMinorSteps = qRound( stepSize / (
double) minStepSize );
619 for (
int i = 1; i < numMinorSteps; i++ )
621 const double minorValue =
624 if ( ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 ) )
625 mediumTicks += minorValue;
627 minorTicks += minorValue;
644 const QDateTime& minDate,
const QDateTime& maxDate,
645 double stepSize,
int maxMinSteps )
651 double minStepSize = 0.0;
653 if ( maxMinSteps > 1 )
659 int numMinorSteps = 0;
660 if ( minStepSize > 0.0 )
661 numMinorSteps =
qwtFloor( stepSize / minStepSize );
663 bool dateBC = minDate.date().year() < -1;
665 for ( QDateTime dt = minDate; dt <= maxDate;
666 dt = dt.addYears( stepSize ) )
668 if ( dateBC && dt.date().year() > 1 )
671 dt = dt.addYears( -1 );
680 for (
int i = 1; i < numMinorSteps; i++ )
684 const double years = qRound( i * minStepSize );
685 if ( years >= std::numeric_limits< int >::max() / 12 )
687 tickDate = dt.addYears( years );
691 tickDate = dt.addMonths( qRound( years * 12 ) );
694 const bool isMedium = ( numMinorSteps > 2 ) &&
695 ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 );
699 mediumTicks += minorValue;
701 minorTicks += minorValue;
870 const QDateTime& minDate,
const QDateTime& maxDate,
873 const double jdMin = minDate.date().toJulianDay();
874 const double jdMax = maxDate.date().toJulianDay();
876 if ( ( jdMax - jdMin ) / 365 > maxSteps )
880 if ( months > maxSteps * 6 )
888 if ( days > 4 * maxSteps * 7 )
892 if ( days > maxSteps * 7 )
896 if ( hours > maxSteps * 24 )
901 if ( seconds >= maxSteps * 3600 )
904 if ( seconds >= maxSteps * 60 )
907 if ( seconds >= maxSteps )
930 double& x1,
double& x2,
double& stepSize )
const 946 if ( interval.
width() == 0.0 )
952 if ( from.isValid() && to.isValid() )
954 if ( maxNumSteps < 1 )
962 const double stepWidth =
qwtDivideScale( width, maxNumSteps, intvType );
965 const QDateTime d1 =
alignDate( from, stepWidth, intvType,
false );
966 const QDateTime d2 =
alignDate( to, stepWidth, intvType,
true );
981 stepSize = -stepSize;
997 int maxMajorSteps,
int maxMinorSteps,
double stepSize )
const 999 if ( maxMajorSteps < 1 )
1002 const double min =
qwtMinF( x1, x2 );
1003 const double max =
qwtMaxF( x1, x2 );
1011 stepSize = qAbs( stepSize );
1012 if ( stepSize > 0.0 )
1018 maxMajorSteps =
qwtCeil( ( max - min ) / stepSize );
1030 maxMajorSteps, maxMinorSteps, stepSize );
1038 maxMajorSteps, maxMinorSteps, intvType );
1043 scaleDiv = scaleDiv.
bounded( min, max );
1053 const QDateTime& minDate,
const QDateTime& maxDate,
1054 int maxMajorSteps,
int maxMinorSteps,
1060 maxMajorSteps, intervalType );
1063 QDateTime dt0 =
alignDate( minDate, stepSize, intervalType,
false );
1064 if ( !dt0.isValid() )
1068 dt0 =
alignDate( minDate, stepSize, intervalType,
true );
1076 stepSize, maxMinorSteps, intervalType );
1083 stepSize, maxMinorSteps );
1088 stepSize, maxMinorSteps );
1113 const QDateTime& dateTime,
double stepSize,
1118 QDateTime dt = dateTime;
1120 if ( dateTime.timeSpec() == Qt::OffsetFromUTC )
1122 #if QT_VERSION >= 0x050200 1123 dt.setOffsetFromUtc( 0 );
1125 dt.setUtcOffset( 0 );
1129 switch( intervalType )
1134 dt.time().msec(), stepSize, up );
1137 dt = dt.addMSecs( ms );
1143 int second = dt.time().second();
1146 if ( dt.time().msec() > 0 )
1153 dt = dt.addSecs( s );
1159 int minute = dt.time().minute();
1162 if ( dt.time().msec() > 0 || dt.time().second() > 0 )
1169 dt = dt.addSecs( m * 60 );
1175 int hour = dt.time().hour();
1178 if ( dt.time().msec() > 0 || dt.time().second() > 0
1179 || dt.time().minute() > 0 )
1187 dt = dt.addSecs( h * 3600 );
1197 int day = dt.date().dayOfYear();
1200 if ( dt.time() > QTime( 0, 0 ) )
1207 dt = dt.addDays( d - 1 );
1216 int numWeeks = date.daysTo( dt.date() ) / 7;
1219 if ( dt.time() > QTime( 0, 0 ) ||
1220 date.daysTo( dt.date() ) % 7 )
1230 dt = dt.addDays( d );
1236 int month = dt.date().month();
1239 if ( dt.date().day() > 1 ||
1240 dt.time() > QTime( 0, 0 ) )
1249 dt = dt.addMonths( m );
1255 int year = dateTime.date().year();
1258 if ( dateTime.date().dayOfYear() > 1 ||
1259 dt.time() > QTime( 0, 0 ) )
1271 dt.setDate( QDate( stepSize, 1, 1 ).addYears( -stepSize ) );
1275 dt.setDate( QDate( y, 1, 1 ) );
1282 if ( dateTime.timeSpec() == Qt::OffsetFromUTC )
1284 #if QT_VERSION >= 0x050200 1285 dt.setOffsetFromUtc( dateTime.offsetFromUtc() );
1287 dt.setUtcOffset( dateTime.utcOffset() );
1305 if ( !dt.isValid() )
1307 const QDate date = ( value <= 0.0 )
1316 #if QT_VERSION >= 0x050200
The interval is related to weeks.
QwtScaleDiv buildScaleDiv(const QDateTime &, const QDateTime &, int maxMajorSteps, int maxMinorSteps, QwtDate::IntervalType) const
The interval is related to years.
QwtDate::Week0Type week0Type() const
void setTimeSpec(Qt::TimeSpec)
The interval is related to months.
static double qwtDivideScale(double intervalSize, int numSteps, QwtDate::IntervalType intervalType)
static double qwtDivideMajorStep(double stepSize, int maxMinSteps, QwtDate::IntervalType intervalType)
static int qwtStepCount(int intervalSize, int maxSteps, const int limits[], size_t numLimits)
double lowerMargin() const
QwtInterval symmetrize(double value) const
A class representing an interval.
void setWeek0Type(QwtDate::Week0Type)
static QwtScaleDiv qwtDivideToMonths(QDateTime &minDate, const QDateTime &maxDate, double stepSize, int maxMinSteps)
QWT_CONSTEXPR float qwtMaxF(float a, float b)
void setTicks(int tickType, const QList< double > &)
virtual QwtScaleDiv divideScale(double x1, double x2, int maxMajorSteps, int maxMinorSteps, double stepSize=0.0) const QWT_OVERRIDE
Calculate a scale division for a date/time interval.
QwtInterval extend(double value) const
Extend the interval.
virtual ~QwtDateScaleEngine()
Destructor.
static double qwtRoundedIntervalWidth(const QDateTime &minDate, const QDateTime &maxDate, QwtDate::IntervalType intervalType)
double upperMargin() const
static QDateTime floor(const QDateTime &, IntervalType)
bool testAttribute(Attribute) const
A class representing a scale division.
static double toDouble(const QDateTime &)
QWT_CONSTEXPR float qwtMinF(float a, float b)
static double divideInterval(double intervalSize, int numSteps, uint base)
int qwtFloor(qreal value)
QwtDate::Week0Type week0Type
void setInterval(double lowerBound, double upperBound)
The interval is related to minutes.
virtual void autoScale(int maxNumSteps, double &x1, double &x2, double &stepSize) const QWT_OVERRIDE
QwtDateScaleEngine(Qt::TimeSpec=Qt::LocalTime)
Constructor.
virtual QDateTime alignDate(const QDateTime &, double stepSize, QwtDate::IntervalType, bool up) const
The interval is related to hours.
static int utcOffset(const QDateTime &)
void setUtcOffset(int seconds)
QwtScaleDiv bounded(double lowerBound, double upperBound) const
static QwtScaleDiv qwtDivideToYears(const QDateTime &minDate, const QDateTime &maxDate, double stepSize, int maxMinSteps)
static QwtScaleDiv qwtDivideToSeconds(const QDateTime &minDate, const QDateTime &maxDate, double stepSize, int maxMinSteps, QwtDate::IntervalType intervalType)
QwtInterval buildInterval(double value) const
Build an interval around a value.
The interval is related to milliseconds.
double width() const
Return the width of an interval.
static int qwtStepSize(int intervalSize, int maxSteps, uint base)
static double qwtMsecsForType(int type)
QDateTime toDateTime(double) const
Build a scale which is symmetric to the reference() value.
static QDateTime ceil(const QDateTime &, IntervalType)
static int qwtAlignValue(double value, double stepSize, bool up)
virtual QwtDate::IntervalType intervalType(const QDateTime &, const QDateTime &, int maxSteps) const
static QList< double > qwtDstTicks(const QDateTime &dateTime, int secondsMajor, int secondsMinor)
static QDate dateOfWeek0(int year, Week0Type)
Date of the first day of the first week for a year.
Qt::TimeSpec timeSpec() const
Turn the scale upside down.
static QDateTime toDateTime(double value, Qt::TimeSpec=Qt::UTC)
A collection of methods around date/time values.
A scale engine for linear scales.
Build a scale which includes the reference() value.
The interval is related to seconds.
static double qwtIntervalWidth(const QDateTime &minDate, const QDateTime &maxDate, QwtDate::IntervalType intervalType)
static int qwtDivideInterval(double intervalSize, int numSteps, const int limits[], size_t numLimits)
PrivateData(Qt::TimeSpec spec)
QwtInterval normalized() const
Normalize the limits of the interval.
virtual QwtScaleDiv divideScale(double x1, double x2, int maxMajorSteps, int maxMinorSteps, double stepSize=0.0) const QWT_OVERRIDE
Calculate a scale division for an interval.
The interval is related to days.