9 * Initial Contributors: |
9 * Initial Contributors: |
10 * Nokia Corporation - initial contribution. |
10 * Nokia Corporation - initial contribution. |
11 * |
11 * |
12 * Contributors: |
12 * Contributors: |
13 * |
13 * |
14 * Description: Utility class providing utility functions to know beginning of the day, maximum/minimum date allowed in calendar, |
14 * Description: ?Description |
15 * day range, on same day, on same month etc. |
|
16 * |
15 * |
17 */ |
16 */ |
18 |
17 |
19 |
18 |
20 |
|
21 //debug |
19 //debug |
|
20 #include <qdatetime.h> |
22 #include "calendarui_debug.h" |
21 #include "calendarui_debug.h" |
23 |
22 |
24 #include <calendateutils.h> |
23 #include "calendateutils.h" |
25 #include <caltime.h> // For Min/MaxValidDate |
24 #include "agendautil.h" |
26 |
25 |
27 // LOCAL CONSTANTS AND MACROS |
26 // LOCAL CONSTANTS AND MACROS |
28 const TInt KDefaultStartTime(8); // 8 am |
27 const int KDefaultStartTime(8); // 8 am ( 0 to 23 hour scale) |
29 |
28 |
30 // ============================ MEMBER FUNCTIONS ============================== |
29 // ============================ MEMBER FUNCTIONS ============================== |
31 |
30 |
32 // ============================ CalenDateUtils ============================== |
31 // ============================ CalenDateUtils ============================== |
33 // ----------------------------------------------------------------------------- |
32 // ----------------------------------------------------------------------------- |
34 // ?classname::?member_function |
33 // ?classname::?member_function |
35 // ?implementation_description |
34 // ?implementation_description |
36 // (other items were commented in a header). |
35 // (other items were commented in a header). |
37 // ----------------------------------------------------------------------------- |
36 // ----------------------------------------------------------------------------- |
38 // |
37 // |
39 EXPORT_C TBool CalenDateUtils::OnSameDay( const TTime& aX, const TTime& aY ) |
38 bool CalenDateUtils::onSameDay( const QDateTime& x, const QDateTime& y ) |
40 { |
39 { |
41 TRACE_ENTRY_POINT; |
40 return x.date().year() == y.date().year() |
42 |
41 && x.date().month() == y.date().month() |
43 TDateTime x = aX.DateTime(); |
42 && x.date().day() == y.date().day(); |
44 TDateTime y = aY.DateTime(); |
43 } |
45 |
44 |
46 TRACE_EXIT_POINT; |
45 // ----------------------------------------------------------------------------- |
47 return x.Year() == y.Year() |
46 // ?classname::?member_function |
48 && x.Month() == y.Month() |
47 // ?implementation_description |
49 && x.Day() == y.Day(); |
48 // (other items were commented in a header). |
50 } |
49 // ----------------------------------------------------------------------------- |
51 |
50 // |
52 // ----------------------------------------------------------------------------- |
51 bool CalenDateUtils::onSameMonth( const QDateTime& x, const QDateTime& y ) |
53 // ?classname::?member_function |
52 { |
54 // ?implementation_description |
53 return ( x.date().year() == y.date().year() && x.date().month() == y.date().month() ); |
55 // (other items were commented in a header). |
54 } |
56 // ----------------------------------------------------------------------------- |
55 |
57 // |
56 // ----------------------------------------------------------------------------- |
58 EXPORT_C TBool CalenDateUtils::OnSameMonth( const TTime& aX, const TTime& aY ) |
57 // ?classname::?member_function |
59 { |
58 // ?implementation_description |
60 TRACE_ENTRY_POINT; |
59 // (other items were commented in a header). |
61 |
60 // ----------------------------------------------------------------------------- |
62 TDateTime x = aX.DateTime(); |
61 // |
63 TDateTime y = aY.DateTime(); |
62 QDateTime CalenDateUtils::beginningOfDay( const QDateTime& startTime ) |
64 |
63 { |
65 TRACE_EXIT_POINT; |
64 QTime zeroTime(0,0,0,0); |
66 return ( x.Year() == y.Year() && x.Month() == y.Month() ); |
65 QDateTime ret(startTime.date(), zeroTime); |
67 } |
66 return ret; |
68 |
67 } |
69 // ----------------------------------------------------------------------------- |
68 |
70 // ?classname::?member_function |
69 // ----------------------------------------------------------------------------- |
71 // ?implementation_description |
70 // ?classname::?member_function |
72 // (other items were commented in a header). |
71 // ?implementation_description |
73 // ----------------------------------------------------------------------------- |
72 // (other items were commented in a header). |
74 // |
73 // ----------------------------------------------------------------------------- |
75 EXPORT_C TTime CalenDateUtils::BeginningOfDay( const TTime& aStartTime ) |
74 // |
76 { |
75 QDateTime CalenDateUtils::displayTimeOnDay( const QDateTime& startTime, |
77 TRACE_ENTRY_POINT; |
76 const QDateTime& day ) |
78 |
77 { |
79 TTime zero(TInt64(0)); |
78 if( ! onSameDay( startTime, day ) ) |
80 |
|
81 TRACE_EXIT_POINT; |
|
82 return zero + aStartTime.DaysFrom( zero ); |
|
83 } |
|
84 |
|
85 // ----------------------------------------------------------------------------- |
|
86 // ?classname::?member_function |
|
87 // ?implementation_description |
|
88 // (other items were commented in a header). |
|
89 // ----------------------------------------------------------------------------- |
|
90 // |
|
91 EXPORT_C TTime CalenDateUtils::DisplayTimeOnDay( const TTime& aStartTime, |
|
92 const TTime& aDay ) |
|
93 { |
|
94 TRACE_ENTRY_POINT; |
|
95 |
|
96 if( ! OnSameDay( aStartTime, aDay ) ) |
|
97 { |
79 { |
98 TRACE_EXIT_POINT; |
80 return beginningOfDay( day ); |
99 return BeginningOfDay( aDay ); |
|
100 } |
81 } |
101 else |
82 else |
102 { |
83 { |
103 TRACE_EXIT_POINT; |
84 return startTime; |
104 return aStartTime; |
|
105 } |
85 } |
106 } |
86 } |
107 |
87 |
108 // ----------------------------------------------------------------------------- |
88 // ----------------------------------------------------------------------------- |
109 // ?classname::?member_function |
89 // ?classname::?member_function |
110 // ?implementation_description |
90 // ?implementation_description |
111 // (other items were commented in a header). |
91 // (other items were commented in a header). |
112 // ----------------------------------------------------------------------------- |
92 // ----------------------------------------------------------------------------- |
113 // |
93 // |
114 EXPORT_C TBool CalenDateUtils::TimeRangesIntersect( const TTime& aXStart, |
94 bool CalenDateUtils::timeRangesIntersect( const QDateTime& xStart, |
115 const TTime& aXEnd, |
95 const QDateTime& xEnd, |
116 const TTime& aYStart, |
96 const QDateTime& yStart, |
117 const TTime& aYEnd ) |
97 const QDateTime& yEnd ) |
118 { |
98 { |
119 TRACE_ENTRY_POINT; |
99 return (! ( yEnd <= xStart || xEnd <= yStart ) |
120 |
100 || (xStart == xEnd && yStart <= xStart && xStart < yEnd) |
121 TRACE_EXIT_POINT; |
101 || (yStart == yEnd && xStart <= yStart && yStart < xEnd) |
122 return (! ( aYEnd <= aXStart || aXEnd <= aYStart )) |
102 || (xStart == xEnd && yStart == yEnd && xStart == yStart)); |
123 || (aXStart == aXEnd && aYStart <= aXStart && aXStart < aYEnd) |
103 } |
124 || (aYStart == aYEnd && aXStart <= aYStart && aYStart < aXEnd) |
104 |
125 || (aXStart == aXEnd && aYStart == aYEnd && aXStart == aYStart); |
105 // ----------------------------------------------------------------------------- |
126 } |
106 // ?classname::?member_function |
127 |
107 // ?implementation_description |
128 // ----------------------------------------------------------------------------- |
108 // (other items were commented in a header). |
129 // ?classname::?member_function |
109 // ----------------------------------------------------------------------------- |
130 // ?implementation_description |
110 // |
131 // (other items were commented in a header). |
111 bool CalenDateUtils::isValidDay( const QDateTime& time ) |
132 // ----------------------------------------------------------------------------- |
112 { |
133 // |
|
134 EXPORT_C TBool CalenDateUtils::IsValidDay( const TTime& aTime ) |
|
135 { |
|
136 TRACE_ENTRY_POINT; |
|
137 |
|
138 // Interim API supports range from 1900-2100, |
113 // Interim API supports range from 1900-2100, |
139 TRACE_EXIT_POINT; |
114 return ( minTime() <= time && time <= maxTime() ); |
140 return ( MinTime() <= aTime && aTime <= MaxTime() ); |
115 } |
141 } |
116 |
142 |
117 // ----------------------------------------------------------------------------- |
143 // ----------------------------------------------------------------------------- |
118 // ?classname::?member_function |
144 // ?classname::?member_function |
119 // ?implementation_description |
145 // ?implementation_description |
120 // (other items were commented in a header). |
146 // (other items were commented in a header). |
121 // ----------------------------------------------------------------------------- |
147 // ----------------------------------------------------------------------------- |
122 // |
148 // |
123 bool CalenDateUtils::isNullTime( QDateTime& time ) |
149 EXPORT_C void CalenDateUtils::GetDayRangeL( const TTime& aStartDay, |
124 { |
150 const TTime& aEndDay, |
125 return( time.isNull() ); |
151 CalCommon::TCalTimeRange& aRange ) |
126 } |
152 { |
127 |
153 TRACE_ENTRY_POINT; |
128 // ----------------------------------------------------------------------------- |
154 |
129 // ?classname::?member_function |
155 TDateTime start( aStartDay.DateTime() ); |
130 // ?implementation_description |
156 TDateTime end( aEndDay.DateTime() ); |
131 // (other items were commented in a header). |
157 |
132 // ----------------------------------------------------------------------------- |
158 start.SetHour( 0 ); |
133 // |
159 start.SetMinute( 0 ); |
134 QDateTime CalenDateUtils::limitToValidTime( const QDateTime& time ) |
160 start.SetSecond( 0 ); |
135 { |
161 start.SetMicroSecond( 0 ); |
136 QDateTime valid = time; |
162 |
137 valid = valid > maxTime() ? maxTime() : valid; |
163 end.SetHour( 23 ); |
138 valid = valid < minTime() ? minTime() : valid; |
164 end.SetMinute( 59 ); |
139 |
165 end.SetSecond( 59 ); |
|
166 end.SetMicroSecond( 0 ); |
|
167 |
|
168 // prevent overflow |
|
169 TCalTime endDate; |
|
170 endDate.SetTimeLocalL( LimitToValidTime( TTime( end ) ) ); |
|
171 |
|
172 TCalTime startDate; |
|
173 startDate.SetTimeLocalL( LimitToValidTime( TTime( start ) ) ); |
|
174 |
|
175 CalCommon::TCalTimeRange dayrange( startDate, endDate ); |
|
176 |
|
177 aRange = dayrange; |
|
178 |
|
179 TRACE_EXIT_POINT; |
|
180 } |
|
181 |
|
182 // ----------------------------------------------------------------------------- |
|
183 // ?classname::?member_function |
|
184 // ?implementation_description |
|
185 // (other items were commented in a header). |
|
186 // ----------------------------------------------------------------------------- |
|
187 // |
|
188 EXPORT_C TBool CalenDateUtils::IsNullTimeL( TCalTime& aTime ) |
|
189 { |
|
190 TRACE_ENTRY_POINT; |
|
191 |
|
192 TRACE_EXIT_POINT; |
|
193 return( aTime.TimeLocalL() == Time::NullTTime() ); |
|
194 } |
|
195 |
|
196 // ----------------------------------------------------------------------------- |
|
197 // ?classname::?member_function |
|
198 // ?implementation_description |
|
199 // (other items were commented in a header). |
|
200 // ----------------------------------------------------------------------------- |
|
201 // |
|
202 EXPORT_C TTime CalenDateUtils::LimitToValidTime( const TTime& aTime ) |
|
203 { |
|
204 TRACE_ENTRY_POINT; |
|
205 |
|
206 TTime valid = aTime; |
|
207 valid = valid > MaxTime() ? MaxTime() : valid; |
|
208 valid = valid < MinTime() ? MinTime() : valid; |
|
209 |
|
210 TRACE_EXIT_POINT; |
|
211 return valid; |
140 return valid; |
212 } |
141 } |
213 |
142 |
214 // ----------------------------------------------------------------------------- |
143 // ----------------------------------------------------------------------------- |
215 // ?classname::?member_function |
144 // ?classname::?member_function |
216 // Returns maximum time allowed, 31.12.2100 0:00 is max so 30.12.2100 is last actual |
145 // Returns maximum time allowed, 31.12.2100 0:00 is max so 30.12.2100 is last actual |
217 // date to be used. |
146 // date to be used. |
218 // (other items were commented in a header). |
147 // (other items were commented in a header). |
219 // ----------------------------------------------------------------------------- |
148 // ----------------------------------------------------------------------------- |
220 // |
149 // |
221 EXPORT_C TTime CalenDateUtils::MaxTime() |
150 QDateTime CalenDateUtils::maxTime() |
222 { |
151 { |
223 TRACE_ENTRY_POINT; |
152 return AgendaUtil::maxTime(); |
|
153 } |
|
154 |
|
155 // ----------------------------------------------------------------------------- |
|
156 // ?classname::?member_function |
|
157 // Returns minimum time allowed, 1.1.1900 0:00 is min |
|
158 // (other items were commented in a header). |
|
159 // ----------------------------------------------------------------------------- |
|
160 // |
|
161 QDateTime CalenDateUtils::minTime() |
|
162 { |
|
163 return AgendaUtil::minTime(); |
|
164 } |
|
165 |
|
166 // ----------------------------------------------------------------------------- |
|
167 // (other items were commented in a header). |
|
168 // ----------------------------------------------------------------------------- |
|
169 // |
|
170 int CalenDateUtils::timeOfDay( const QDateTime& dateTime ) |
|
171 { |
|
172 QDateTime midnight = CalenDateUtils::beginningOfDay( dateTime ); |
|
173 int resultInSec = midnight.secsTo(dateTime); |
224 |
174 |
225 TTime time( TCalTime::MaxTime() - TTimeIntervalMinutes( 1 ) ); |
175 return (resultInSec/60); |
226 |
176 } |
227 TRACE_EXIT_POINT; |
177 |
228 return time; |
178 // ----------------------------------------------------------------------------- |
229 } |
179 // (other items were commented in a header). |
230 |
180 // ----------------------------------------------------------------------------- |
231 // ----------------------------------------------------------------------------- |
181 // |
232 // ?classname::?member_function |
182 QDateTime CalenDateUtils::roundToPreviousHour( const QDateTime& dateTime ) |
233 // Returns minimum time allowed, 1.1.1900 0:00 is min |
183 { |
234 // (other items were commented in a header). |
184 QTime time = dateTime.time(); |
235 // ----------------------------------------------------------------------------- |
185 time.setHMS(time.hour(),0,0,0); |
236 // |
186 return QDateTime( dateTime.date(), time ); |
237 EXPORT_C TTime CalenDateUtils::MinTime() |
187 } |
238 { |
188 |
239 TRACE_ENTRY_POINT; |
189 // ----------------------------------------------------------------------------- |
240 |
190 // (other items were commented in a header). |
241 TRACE_EXIT_POINT; |
191 // ----------------------------------------------------------------------------- |
242 return TCalTime::MinTime(); |
192 // |
243 } |
193 int CalenDateUtils::roundToPreviousHour( const int& minutes ) |
244 |
194 { |
245 // ----------------------------------------------------------------------------- |
195 return ( (minutes / 60) * 60 ); |
246 // (other items were commented in a header). |
196 } |
247 // ----------------------------------------------------------------------------- |
197 |
248 // |
198 // ----------------------------------------------------------------------------- |
249 EXPORT_C TTimeIntervalMinutes CalenDateUtils::TimeOfDay( const TTime& aDateTime ) |
199 // (other items were commented in a header). |
250 { |
200 // ----------------------------------------------------------------------------- |
251 TRACE_ENTRY_POINT; |
201 // |
252 |
202 QDateTime CalenDateUtils::now() |
253 TTime midnight = CalenDateUtils::BeginningOfDay( aDateTime ); |
203 { |
254 TTimeIntervalMinutes result; |
204 TTime currentTime; |
255 aDateTime.MinutesFrom( midnight, result ); |
205 currentTime.HomeTime(); |
256 |
206 TDateTime curDateTime = currentTime.DateTime(); |
257 TRACE_EXIT_POINT; |
207 QDateTime ret; |
258 return result; |
208 ret.setDate(QDate(curDateTime.Year(), curDateTime.Month() + 1, curDateTime.Day() + 1)); |
259 } |
209 ret.setTime(QTime(curDateTime.Hour(), curDateTime.Minute(), curDateTime.Second(), curDateTime.MicroSecond())); |
260 |
210 // TODO: need to use QDateTime::currentDateTime() from QT4.6 onwards |
261 // ----------------------------------------------------------------------------- |
211 //return QDateTime::currentDateTime(); |
262 // (other items were commented in a header). |
212 return ret; |
263 // ----------------------------------------------------------------------------- |
213 } |
264 // |
214 |
265 EXPORT_C TTime CalenDateUtils::RoundToPreviousHour( const TTime& aTime ) |
215 // ----------------------------------------------------------------------------- |
266 { |
216 // (other items were commented in a header). |
267 TRACE_ENTRY_POINT; |
217 // ----------------------------------------------------------------------------- |
268 |
218 // |
269 TDateTime dt = aTime.DateTime(); |
219 QDateTime CalenDateUtils::today() |
270 dt.SetMinute(0); |
220 { |
271 dt.SetSecond(0); |
221 return CalenDateUtils::beginningOfDay( now() ); |
272 dt.SetMicroSecond(0); |
222 } |
273 |
223 |
274 TRACE_EXIT_POINT; |
224 // ----------------------------------------------------------------------------- |
275 return TTime( dt ); |
225 // (other items were commented in a header). |
276 } |
226 // ----------------------------------------------------------------------------- |
277 |
227 // |
278 // ----------------------------------------------------------------------------- |
228 bool CalenDateUtils::isOnToday( const QDateTime& time ) |
279 // (other items were commented in a header). |
229 { |
280 // ----------------------------------------------------------------------------- |
230 return CalenDateUtils::onSameDay( time, today() ); |
281 // |
231 } |
282 EXPORT_C TTimeIntervalMinutes CalenDateUtils::RoundToPreviousHour( const TTimeIntervalMinutes& aMinutes ) |
232 |
283 { |
233 // ----------------------------------------------------------------------------- |
284 TRACE_ENTRY_POINT; |
234 // (other items were commented in a header). |
285 |
235 // ----------------------------------------------------------------------------- |
286 TRACE_EXIT_POINT; |
236 // |
287 return TTimeIntervalMinutes( (aMinutes.Int() / 60) * 60 ); |
237 QDateTime CalenDateUtils::defaultTime( const QDateTime& date ) |
288 } |
238 { |
289 |
239 QDateTime dateTime; |
290 // ----------------------------------------------------------------------------- |
|
291 // (other items were commented in a header). |
|
292 // ----------------------------------------------------------------------------- |
|
293 // |
|
294 EXPORT_C TTime CalenDateUtils::Now() |
|
295 { |
|
296 TRACE_ENTRY_POINT; |
|
297 |
|
298 TTime now; |
|
299 now.HomeTime(); |
|
300 |
|
301 TRACE_EXIT_POINT; |
|
302 return now; |
|
303 } |
|
304 |
|
305 // ----------------------------------------------------------------------------- |
|
306 // (other items were commented in a header). |
|
307 // ----------------------------------------------------------------------------- |
|
308 // |
|
309 EXPORT_C TTime CalenDateUtils::Today() |
|
310 { |
|
311 TRACE_ENTRY_POINT; |
|
312 |
|
313 TRACE_EXIT_POINT; |
|
314 return CalenDateUtils::BeginningOfDay( Now() ); |
|
315 } |
|
316 |
|
317 // ----------------------------------------------------------------------------- |
|
318 // (other items were commented in a header). |
|
319 // ----------------------------------------------------------------------------- |
|
320 // |
|
321 EXPORT_C TBool CalenDateUtils::IsOnToday( const TTime& aTime ) |
|
322 { |
|
323 TRACE_ENTRY_POINT; |
|
324 |
|
325 TRACE_EXIT_POINT; |
|
326 return CalenDateUtils::OnSameDay( aTime, Today() ); |
|
327 } |
|
328 |
|
329 // ----------------------------------------------------------------------------- |
|
330 // (other items were commented in a header). |
|
331 // ----------------------------------------------------------------------------- |
|
332 // |
|
333 EXPORT_C TTime CalenDateUtils::DefaultTime( const TTime& aDate ) |
|
334 { |
|
335 TRACE_ENTRY_POINT; |
|
336 |
|
337 TTime dateTime( Time::NullTTime() ); |
|
338 // DD:MM:YY @ hh:mm:ss |
240 // DD:MM:YY @ hh:mm:ss |
339 dateTime = CalenDateUtils::BeginningOfDay( aDate ); |
241 dateTime = CalenDateUtils::beginningOfDay( date ); |
340 // DD:MM:YY @ 00:00:00 |
242 // DD:MM:YY @ 00:00:00 |
341 dateTime += TTimeIntervalHours( KDefaultStartTime ); // DD:MM:YY @ 08:00 am |
243 QTime time(KDefaultStartTime, 0, 0, 0); |
342 |
244 dateTime.setTime(time); // DD:MM:YY @ 08:00 am |
343 TRACE_EXIT_POINT; |
245 |
344 return dateTime; |
246 return dateTime; |
345 } |
247 } |
346 |
248 |
|
249 // ----------------------------------------------------------------------------- |
|
250 // (other items were commented in a header). |
|
251 // ----------------------------------------------------------------------------- |
|
252 // |
|
253 QDateTime CalenDateUtils::pastOf(const QDateTime& dateTime, int numOfDays) |
|
254 { |
|
255 QDateTime result; |
|
256 int dayNumber = dateTime.date().day(); |
|
257 int numOfDaysInMonth = dayNumber; |
|
258 int month = dateTime.date().month(); |
|
259 int year = dateTime.date().year(); |
|
260 int buff = numOfDays; |
|
261 QDate date(year, month, dayNumber); |
|
262 while(buff > numOfDaysInMonth) |
|
263 { |
|
264 if(month == 1) { |
|
265 // If January, |
|
266 month = 12; // December |
|
267 year--; |
|
268 } |
|
269 else { |
|
270 month--; |
|
271 } |
|
272 // Create the qdate with these details |
|
273 date.setDate(year, month, 1); |
|
274 // check to see if it goes beyond the next month also |
|
275 buff = buff - numOfDaysInMonth; |
|
276 numOfDaysInMonth = date.daysInMonth(); |
|
277 } |
|
278 |
|
279 // Substract buff days from end of the month |
|
280 int day = numOfDaysInMonth - buff; |
|
281 date.setYMD(date.year(), date.month(), day); |
|
282 result.setDate(date); |
|
283 result.setTime(dateTime.time()); |
|
284 return result; |
|
285 } |
|
286 |
|
287 // ----------------------------------------------------------------------------- |
|
288 // (other items were commented in a header). |
|
289 // ----------------------------------------------------------------------------- |
|
290 // |
|
291 QDateTime CalenDateUtils::futureOf(const QDateTime& dateTime, int numOfDays) |
|
292 { |
|
293 QDateTime result; |
|
294 int dayNumber = dateTime.date().day(); |
|
295 int numOfDaysInMonth = dateTime.date().daysInMonth(); |
|
296 int month = dateTime.date().month(); |
|
297 int year = dateTime.date().year(); |
|
298 int buff = numOfDays; |
|
299 QDate date(year, month, dayNumber); |
|
300 while(dayNumber + buff > numOfDaysInMonth) |
|
301 { |
|
302 if(month == 12) { |
|
303 // If December, |
|
304 month = 1; // January |
|
305 year++; |
|
306 } |
|
307 else { |
|
308 month++; |
|
309 } |
|
310 // Create the qdate with these details |
|
311 date.setDate(year, month, 1); |
|
312 // check to see if it goes beyond the next month also |
|
313 buff = buff - (numOfDaysInMonth - dayNumber); |
|
314 dayNumber = 0; |
|
315 numOfDaysInMonth = date.daysInMonth(); |
|
316 } |
|
317 |
|
318 // Add the buff days to the day number to get the result |
|
319 int day = dayNumber + buff; |
|
320 |
|
321 date.setYMD(date.year(), date.month(), day); |
|
322 result.setDate(date); |
|
323 result.setTime(dateTime.time()); |
|
324 return result; |
|
325 } |
347 // End of File |
326 // End of File |