00001 /******************************************************************************* 00002 00003 @file UCalendar.d 00004 00005 Copyright (c) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 4. Derivative works are permitted, but they must carry this notice 00027 in full and credit the original source. 00028 00029 00030 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00031 00032 00033 @version Initial version, November 2004 00034 @author Kris 00035 00036 Note that this package and documentation is built around the ICU 00037 project (http://oss.software.ibm.com/icu/). Below is the license 00038 statement as specified by that software: 00039 00040 00041 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00042 00043 00044 ICU License - ICU 1.8.1 and later 00045 00046 COPYRIGHT AND PERMISSION NOTICE 00047 00048 Copyright (c) 1995-2003 International Business Machines Corporation and 00049 others. 00050 00051 All rights reserved. 00052 00053 Permission is hereby granted, free of charge, to any person obtaining a 00054 copy of this software and associated documentation files (the 00055 "Software"), to deal in the Software without restriction, including 00056 without limitation the rights to use, copy, modify, merge, publish, 00057 distribute, and/or sell copies of the Software, and to permit persons 00058 to whom the Software is furnished to do so, provided that the above 00059 copyright notice(s) and this permission notice appear in all copies of 00060 the Software and that both the above copyright notice(s) and this 00061 permission notice appear in supporting documentation. 00062 00063 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00064 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00065 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 00066 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 00067 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 00068 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 00069 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00070 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00071 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00072 00073 Except as contained in this notice, the name of a copyright holder 00074 shall not be used in advertising or otherwise to promote the sale, use 00075 or other dealings in this Software without prior written authorization 00076 of the copyright holder. 00077 00078 ---------------------------------------------------------------------- 00079 00080 All trademarks and registered trademarks mentioned herein are the 00081 property of their respective owners. 00082 00083 *******************************************************************************/ 00084 00085 module mango.icu.UCalendar; 00086 00087 private import mango.icu.ICU, 00088 mango.icu.UString; 00089 00090 public import mango.icu.ULocale, 00091 mango.icu.UTimeZone; 00092 00093 /******************************************************************************* 00094 00095 UCalendar is used for converting between a UDate object and 00096 a set of integer fields such as Year, Month, Day, 00097 Hour, and so on. (A UDate object represents a specific instant 00098 in time with millisecond precision. See UDate for information about 00099 the UDate) 00100 00101 Types of UCalendar interpret a UDate according to the rules of a 00102 specific calendar system. UCalendar supports Traditional & Gregorian. 00103 00104 A UCalendar object can produce all the time field values needed to 00105 implement the date-time formatting for a particular language and 00106 calendar style (for example, Japanese-Gregorian, Japanese-Traditional). 00107 00108 When computing a UDate from time fields, two special circumstances 00109 may arise: there may be insufficient information to compute the UDate 00110 (such as only year and month but no day in the month), or there may be 00111 inconsistent information (such as "Tuesday, July 15, 1996" -- July 15, 00112 1996 is actually a Monday). 00113 00114 Insufficient information. The calendar will use default information 00115 to specify the missing fields. This may vary by calendar; for the 00116 Gregorian calendar, the default for a field is the same as that of 00117 the start of the epoch: i.e., Year = 1970, Month = January, 00118 Date = 1, etc. 00119 00120 Inconsistent information. If fields conflict, the calendar will give 00121 preference to fields set more recently. For example, when determining 00122 the day, the calendar will look for one of the following combinations 00123 of fields. The most recent combination, as determined by the most 00124 recently set single field, will be used. 00125 00126 See http://oss.software.ibm.com/icu/apiref/udat_8h.html for full 00127 details. 00128 00129 *******************************************************************************/ 00130 00131 class UCalendar : ICU 00132 { 00133 package Handle handle; 00134 00135 typedef double UDate; 00136 00137 //Possible types of UCalendars 00138 public enum Type 00139 { 00140 Traditional, 00141 Gregorian 00142 } 00143 00144 // Possible fields in a UCalendar 00145 public enum DateFields 00146 { 00147 Era, 00148 Year, 00149 Month, 00150 WeekOfYear, 00151 WeekOfMonth, 00152 Date, 00153 DayOfYear, 00154 DayOfWeek, 00155 DayOfWeekInMonth, 00156 AmPm, 00157 Hour, 00158 HourOfDay, 00159 Minute, 00160 Second, 00161 Millisecond, 00162 ZoneOffset, 00163 DstOffset, 00164 YearWoy, 00165 DowLocal, 00166 ExtendedYear, 00167 JulianDay, 00168 MillisecondsInDay, 00169 FieldCount, 00170 DayOfMonth = Date 00171 } 00172 00173 // Possible days of the week in a UCalendar 00174 public enum DaysOfWeek 00175 { 00176 Sunday = 1, 00177 Monday, 00178 Tuesday, 00179 Wednesday, 00180 Thursday, 00181 Friday, 00182 Saturday 00183 } 00184 00185 // Possible months in a UCalendar 00186 public enum Months 00187 { 00188 January, 00189 February, 00190 March, 00191 April, 00192 May, 00193 June, 00194 July, 00195 August, 00196 September, 00197 October, 00198 November, 00199 December, 00200 UnDecimber 00201 } 00202 00203 // Possible AM/PM values in a UCalendar 00204 public enum AMPMs 00205 { 00206 AM, 00207 PM 00208 } 00209 00210 // Possible formats for a UCalendar's display name 00211 public enum DisplayNameType 00212 { 00213 Standard, 00214 ShortStandard, 00215 DST, 00216 ShortDST 00217 } 00218 00219 // Possible limit values for a UCalendar 00220 public enum Limit 00221 { 00222 Minimum, 00223 Maximum, 00224 GreatestMinimum, 00225 LeastMaximum, 00226 ActualMinimum, 00227 ActualMaximum 00228 } 00229 00230 // Types of UCalendar attributes 00231 private enum Attribute 00232 { 00233 Lenient, // unused: set from UDateFormat instead 00234 FirstDayOfWeek, 00235 MinimalDaysInFirstWeek 00236 } 00237 00238 /*********************************************************************** 00239 00240 Open a UCalendar. A UCalendar may be used to convert a 00241 millisecond value to a year, month, and day 00242 00243 ***********************************************************************/ 00244 00245 this (inout UTimeZone zone, inout ULocale locale, Type type = Type.Traditional) 00246 { 00247 Error e; 00248 00249 handle = ucal_open (zone.name, zone.name.length, toString(locale.name), type, e); 00250 testError (e, "failed to open calendar"); 00251 } 00252 00253 /*********************************************************************** 00254 00255 Internal only: Open a UCalendar with the given handle 00256 00257 ***********************************************************************/ 00258 00259 package this (Handle handle) 00260 { 00261 this.handle = handle; 00262 } 00263 00264 /*********************************************************************** 00265 00266 Close this UCalendar 00267 00268 ***********************************************************************/ 00269 00270 ~this () 00271 { 00272 ucal_close (handle); 00273 } 00274 00275 /*********************************************************************** 00276 00277 Set the TimeZone used by a UCalendar 00278 00279 ***********************************************************************/ 00280 00281 void setTimeZone (inout UTimeZone zone) 00282 { 00283 Error e; 00284 00285 return ucal_setTimeZone (handle, zone.name, zone.name.length, e); 00286 testError (e, "failed to set calendar time zone"); 00287 } 00288 00289 /*********************************************************************** 00290 00291 Get display name of the TimeZone used by this UCalendar 00292 00293 ***********************************************************************/ 00294 00295 void getTimeZoneName (UString s, inout ULocale locale, DisplayNameType type=DisplayNameType.Standard) 00296 { 00297 uint format (wchar* dst, uint length, inout ICU.Error e) 00298 { 00299 return ucal_getTimeZoneDisplayName (handle, type, toString(locale.name), dst, length, e); 00300 } 00301 00302 s.format (&format, "failed to get time zone name"); 00303 } 00304 00305 /*********************************************************************** 00306 00307 Determine if a UCalendar is currently in daylight savings 00308 time 00309 00310 ***********************************************************************/ 00311 00312 bool inDaylightTime () 00313 { 00314 Error e; 00315 00316 byte x = ucal_inDaylightTime (handle, e); 00317 testError (e, "failed to test calendar daylight time"); 00318 return x != 0; 00319 } 00320 00321 /*********************************************************************** 00322 00323 Get the current date and time 00324 00325 ***********************************************************************/ 00326 00327 UDate getNow () 00328 { 00329 return ucal_getNow (); 00330 } 00331 00332 /*********************************************************************** 00333 00334 Get a UCalendar's current time in millis. The time is 00335 represented as milliseconds from the epoch 00336 00337 ***********************************************************************/ 00338 00339 UDate getMillis () 00340 { 00341 Error e; 00342 00343 return ucal_getMillis (handle, e); 00344 testError (e, "failed to get time"); 00345 } 00346 00347 /*********************************************************************** 00348 00349 Set a UCalendar's current time in millis. The time is 00350 represented as milliseconds from the epoch 00351 00352 ***********************************************************************/ 00353 00354 void setMillis (UDate date) 00355 { 00356 Error e; 00357 00358 return ucal_setMillis (handle, date, e); 00359 testError (e, "failed to set time"); 00360 } 00361 00362 /*********************************************************************** 00363 00364 Set a UCalendar's current date 00365 00366 ***********************************************************************/ 00367 00368 void setDate (uint year, Months month, uint date) 00369 { 00370 Error e; 00371 00372 return ucal_setDate (handle, year, month, date, e); 00373 testError (e, "failed to set date"); 00374 } 00375 00376 /*********************************************************************** 00377 00378 Set a UCalendar's current date 00379 00380 ***********************************************************************/ 00381 00382 void setDateTime (uint year, Months month, uint date, uint hour, uint minute, uint second) 00383 { 00384 Error e; 00385 00386 return ucal_setDateTime (handle, year, month, date, hour, minute, second, e); 00387 testError (e, "failed to set date/time"); 00388 } 00389 00390 /*********************************************************************** 00391 00392 Returns TRUE if the given Calendar object is equivalent 00393 to this one 00394 00395 ***********************************************************************/ 00396 00397 bool isEquivalent (UCalendar when) 00398 { 00399 return ucal_equivalentTo (handle, when.handle) != 0; 00400 } 00401 00402 /*********************************************************************** 00403 00404 Compares the Calendar time 00405 00406 ***********************************************************************/ 00407 00408 bool isEqual (UCalendar when) 00409 { 00410 return (this is when || getMillis == when.getMillis); 00411 } 00412 00413 /*********************************************************************** 00414 00415 Returns true if this Calendar's current time is before 00416 "when"'s current time 00417 00418 ***********************************************************************/ 00419 00420 bool isBefore (UCalendar when) 00421 { 00422 return (this !is when || getMillis < when.getMillis); 00423 } 00424 00425 /*********************************************************************** 00426 00427 Returns true if this Calendar's current time is after 00428 "when"'s current time 00429 00430 ***********************************************************************/ 00431 00432 bool isAfter (UCalendar when) 00433 { 00434 return (this !is when || getMillis > when.getMillis); 00435 } 00436 00437 /*********************************************************************** 00438 00439 Add a specified signed amount to a particular field in a 00440 UCalendar 00441 00442 ***********************************************************************/ 00443 00444 void add (DateFields field, uint amount) 00445 { 00446 Error e; 00447 00448 return ucal_add (handle, field, amount, e); 00449 testError (e, "failed to add to calendar"); 00450 } 00451 00452 /*********************************************************************** 00453 00454 Add a specified signed amount to a particular field in a 00455 UCalendar 00456 00457 ***********************************************************************/ 00458 00459 void roll (DateFields field, uint amount) 00460 { 00461 Error e; 00462 00463 return ucal_roll (handle, field, amount, e); 00464 testError (e, "failed to roll calendar"); 00465 } 00466 00467 /*********************************************************************** 00468 00469 Get the current value of a field from a UCalendar 00470 00471 ***********************************************************************/ 00472 00473 uint get (DateFields field) 00474 { 00475 Error e; 00476 00477 uint x = ucal_get (handle, field, e); 00478 testError (e, "failed to get calendar field"); 00479 return x; 00480 } 00481 00482 /*********************************************************************** 00483 00484 Set the value of a field in a UCalendar 00485 00486 ***********************************************************************/ 00487 00488 void set (DateFields field, uint value) 00489 { 00490 ucal_set (handle, field, value); 00491 } 00492 00493 /*********************************************************************** 00494 00495 Determine if a field in a UCalendar is set 00496 00497 ***********************************************************************/ 00498 00499 bool isSet (DateFields field) 00500 { 00501 return ucal_isSet (handle, field) != 0; 00502 } 00503 00504 /*********************************************************************** 00505 00506 Clear a field in a UCalendar 00507 00508 ***********************************************************************/ 00509 00510 void clearField (DateFields field) 00511 { 00512 ucal_clearField (handle, field); 00513 } 00514 00515 /*********************************************************************** 00516 00517 Clear all fields in a UCalendar 00518 00519 ***********************************************************************/ 00520 00521 void clear () 00522 { 00523 ucal_clear (handle); 00524 } 00525 00526 /*********************************************************************** 00527 00528 Determine a limit for a field in a UCalendar. A limit is a 00529 maximum or minimum value for a field 00530 00531 ***********************************************************************/ 00532 00533 uint getLimit (DateFields field, Limit type) 00534 { 00535 Error e; 00536 00537 uint x = ucal_getLimit (handle, field, type, e); 00538 testError (e, "failed to get calendar limit"); 00539 return x; 00540 } 00541 00542 /*********************************************************************** 00543 00544 ***********************************************************************/ 00545 00546 uint getDaysInFirstWeek () 00547 { 00548 return ucal_getAttribute (handle, Attribute.MinimalDaysInFirstWeek); 00549 } 00550 00551 /*********************************************************************** 00552 00553 ***********************************************************************/ 00554 00555 uint getFirstDayOfWeek () 00556 { 00557 return ucal_getAttribute (handle, Attribute.FirstDayOfWeek); 00558 } 00559 00560 /*********************************************************************** 00561 00562 ***********************************************************************/ 00563 00564 void setDaysInFirstWeek (uint value) 00565 { 00566 ucal_setAttribute (handle, Attribute.MinimalDaysInFirstWeek, value); 00567 } 00568 00569 /*********************************************************************** 00570 00571 ***********************************************************************/ 00572 00573 void setFirstDayOfWeek (uint value) 00574 { 00575 ucal_setAttribute (handle, Attribute.FirstDayOfWeek, value); 00576 } 00577 00578 00579 /*********************************************************************** 00580 00581 Bind the ICU functions from a shared library. This is 00582 complicated by the issues regarding D and DLLs on the 00583 Windows platform 00584 00585 ***********************************************************************/ 00586 00587 private static void* library; 00588 00589 /*********************************************************************** 00590 00591 ***********************************************************************/ 00592 00593 private static extern (C) 00594 { 00595 Handle function (wchar*, uint, char*, Type, inout Error) ucal_open; 00596 void function (Handle) ucal_close; 00597 UDate function () ucal_getNow; 00598 UDate function (Handle, inout Error) ucal_getMillis; 00599 void function (Handle, UDate, inout Error) ucal_setMillis; 00600 void function (Handle, uint, uint, uint, inout Error) ucal_setDate; 00601 void function (Handle, uint, uint, uint, uint, uint, uint, inout Error) ucal_setDateTime; 00602 byte function (Handle, Handle) ucal_equivalentTo; 00603 void function (Handle, uint, uint, inout Error) ucal_add; 00604 void function (Handle, uint, uint, inout Error) ucal_roll; 00605 uint function (Handle, uint, inout Error) ucal_get; 00606 void function (Handle, uint, uint) ucal_set; 00607 byte function (Handle, uint) ucal_isSet; 00608 void function (Handle, uint) ucal_clearField; 00609 void function (Handle) ucal_clear; 00610 uint function (Handle, uint, uint, inout Error) ucal_getLimit; 00611 void function (Handle, wchar*, uint, inout Error) ucal_setTimeZone; 00612 byte function (Handle, uint) ucal_inDaylightTime; 00613 uint function (Handle, uint) ucal_getAttribute; 00614 void function (Handle, uint, uint) ucal_setAttribute; 00615 uint function (Handle, uint, char*, wchar*, uint, inout Error) ucal_getTimeZoneDisplayName; 00616 } 00617 00618 /*********************************************************************** 00619 00620 ***********************************************************************/ 00621 00622 static FunctionLoader.Bind[] targets = 00623 [ 00624 {cast(void**) &ucal_open, "ucal_open"}, 00625 {cast(void**) &ucal_close, "ucal_close"}, 00626 {cast(void**) &ucal_getNow, "ucal_getNow"}, 00627 {cast(void**) &ucal_getMillis, "ucal_getMillis"}, 00628 {cast(void**) &ucal_setMillis, "ucal_setMillis"}, 00629 {cast(void**) &ucal_setDate, "ucal_setDate"}, 00630 {cast(void**) &ucal_setDateTime, "ucal_setDateTime"}, 00631 {cast(void**) &ucal_equivalentTo, "ucal_equivalentTo"}, 00632 {cast(void**) &ucal_add, "ucal_add"}, 00633 {cast(void**) &ucal_roll, "ucal_roll"}, 00634 {cast(void**) &ucal_get, "ucal_get"}, 00635 {cast(void**) &ucal_set, "ucal_set"}, 00636 {cast(void**) &ucal_clearField, "ucal_clearField"}, 00637 {cast(void**) &ucal_clear, "ucal_clear"}, 00638 {cast(void**) &ucal_getLimit, "ucal_getLimit"}, 00639 {cast(void**) &ucal_setTimeZone, "ucal_setTimeZone"}, 00640 {cast(void**) &ucal_inDaylightTime, "ucal_inDaylightTime"}, 00641 {cast(void**) &ucal_getAttribute, "ucal_getAttribute"}, 00642 {cast(void**) &ucal_setAttribute, "ucal_setAttribute"}, 00643 {cast(void**) &ucal_isSet, "ucal_isSet"}, 00644 {cast(void**) &ucal_getTimeZoneDisplayName, "ucal_getTimeZoneDisplayName"}, 00645 ]; 00646 00647 /*********************************************************************** 00648 00649 ***********************************************************************/ 00650 00651 static this () 00652 { 00653 library = FunctionLoader.bind (icuin, targets); 00654 } 00655 00656 /*********************************************************************** 00657 00658 ***********************************************************************/ 00659 00660 static ~this () 00661 { 00662 FunctionLoader.unbind (library); 00663 } 00664 00665 }