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 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 cast(bool) (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 UDate date = ucal_getMillis (handle, e); 00344 testError (e, "failed to get time"); 00345 return date; 00346 } 00347 00348 /*********************************************************************** 00349 00350 Set a UCalendar's current time in millis. The time is 00351 represented as milliseconds from the epoch 00352 00353 ***********************************************************************/ 00354 00355 void setMillis (UDate date) 00356 { 00357 Error e; 00358 00359 ucal_setMillis (handle, date, e); 00360 testError (e, "failed to set time"); 00361 } 00362 00363 /*********************************************************************** 00364 00365 Set a UCalendar's current date 00366 00367 ***********************************************************************/ 00368 00369 void setDate (uint year, Months month, uint date) 00370 { 00371 Error e; 00372 00373 ucal_setDate (handle, year, month, date, e); 00374 testError (e, "failed to set date"); 00375 } 00376 00377 /*********************************************************************** 00378 00379 Set a UCalendar's current date 00380 00381 ***********************************************************************/ 00382 00383 void setDateTime (uint year, Months month, uint date, uint hour, uint minute, uint second) 00384 { 00385 Error e; 00386 00387 ucal_setDateTime (handle, year, month, date, hour, minute, second, e); 00388 testError (e, "failed to set date/time"); 00389 } 00390 00391 /*********************************************************************** 00392 00393 Returns TRUE if the given Calendar object is equivalent 00394 to this one 00395 00396 ***********************************************************************/ 00397 00398 bool isEquivalent (UCalendar when) 00399 { 00400 return cast(bool) (ucal_equivalentTo (handle, when.handle) != 0); 00401 } 00402 00403 /*********************************************************************** 00404 00405 Compares the Calendar time 00406 00407 ***********************************************************************/ 00408 00409 bool isEqual (UCalendar when) 00410 { 00411 return cast(bool) (this is when || getMillis == when.getMillis); 00412 } 00413 00414 /*********************************************************************** 00415 00416 Returns true if this Calendar's current time is before 00417 "when"'s current time 00418 00419 ***********************************************************************/ 00420 00421 bool isBefore (UCalendar when) 00422 { 00423 return cast(bool) (this !is when || getMillis < when.getMillis); 00424 } 00425 00426 /*********************************************************************** 00427 00428 Returns true if this Calendar's current time is after 00429 "when"'s current time 00430 00431 ***********************************************************************/ 00432 00433 bool isAfter (UCalendar when) 00434 { 00435 return cast(bool) (this !is when || getMillis > when.getMillis); 00436 } 00437 00438 /*********************************************************************** 00439 00440 Add a specified signed amount to a particular field in a 00441 UCalendar 00442 00443 ***********************************************************************/ 00444 00445 void add (DateFields field, uint amount) 00446 { 00447 Error e; 00448 00449 ucal_add (handle, field, amount, e); 00450 testError (e, "failed to add to calendar"); 00451 } 00452 00453 /*********************************************************************** 00454 00455 Add a specified signed amount to a particular field in a 00456 UCalendar 00457 00458 ***********************************************************************/ 00459 00460 void roll (DateFields field, uint amount) 00461 { 00462 Error e; 00463 00464 ucal_roll (handle, field, amount, e); 00465 testError (e, "failed to roll calendar"); 00466 } 00467 00468 /*********************************************************************** 00469 00470 Get the current value of a field from a UCalendar 00471 00472 ***********************************************************************/ 00473 00474 uint get (DateFields field) 00475 { 00476 Error e; 00477 00478 uint x = ucal_get (handle, field, e); 00479 testError (e, "failed to get calendar field"); 00480 return x; 00481 } 00482 00483 /*********************************************************************** 00484 00485 Set the value of a field in a UCalendar 00486 00487 ***********************************************************************/ 00488 00489 void set (DateFields field, uint value) 00490 { 00491 ucal_set (handle, field, value); 00492 } 00493 00494 /*********************************************************************** 00495 00496 Determine if a field in a UCalendar is set 00497 00498 ***********************************************************************/ 00499 00500 bool isSet (DateFields field) 00501 { 00502 return cast(bool) (ucal_isSet (handle, field) != 0); 00503 } 00504 00505 /*********************************************************************** 00506 00507 Clear a field in a UCalendar 00508 00509 ***********************************************************************/ 00510 00511 void clearField (DateFields field) 00512 { 00513 ucal_clearField (handle, field); 00514 } 00515 00516 /*********************************************************************** 00517 00518 Clear all fields in a UCalendar 00519 00520 ***********************************************************************/ 00521 00522 void clear () 00523 { 00524 ucal_clear (handle); 00525 } 00526 00527 /*********************************************************************** 00528 00529 Determine a limit for a field in a UCalendar. A limit is a 00530 maximum or minimum value for a field 00531 00532 ***********************************************************************/ 00533 00534 uint getLimit (DateFields field, Limit type) 00535 { 00536 Error e; 00537 00538 uint x = ucal_getLimit (handle, field, type, e); 00539 testError (e, "failed to get calendar limit"); 00540 return x; 00541 } 00542 00543 /*********************************************************************** 00544 00545 ***********************************************************************/ 00546 00547 uint getDaysInFirstWeek () 00548 { 00549 return ucal_getAttribute (handle, Attribute.MinimalDaysInFirstWeek); 00550 } 00551 00552 /*********************************************************************** 00553 00554 ***********************************************************************/ 00555 00556 uint getFirstDayOfWeek () 00557 { 00558 return ucal_getAttribute (handle, Attribute.FirstDayOfWeek); 00559 } 00560 00561 /*********************************************************************** 00562 00563 ***********************************************************************/ 00564 00565 void setDaysInFirstWeek (uint value) 00566 { 00567 ucal_setAttribute (handle, Attribute.MinimalDaysInFirstWeek, value); 00568 } 00569 00570 /*********************************************************************** 00571 00572 ***********************************************************************/ 00573 00574 void setFirstDayOfWeek (uint value) 00575 { 00576 ucal_setAttribute (handle, Attribute.FirstDayOfWeek, value); 00577 } 00578 00579 00580 /*********************************************************************** 00581 00582 Bind the ICU functions from a shared library. This is 00583 complicated by the issues regarding D and DLLs on the 00584 Windows platform 00585 00586 ***********************************************************************/ 00587 00588 private static void* library; 00589 00590 /*********************************************************************** 00591 00592 ***********************************************************************/ 00593 00594 private static extern (C) 00595 { 00596 Handle function (wchar*, uint, char*, Type, inout Error) ucal_open; 00597 void function (Handle) ucal_close; 00598 UDate function () ucal_getNow; 00599 UDate function (Handle, inout Error) ucal_getMillis; 00600 void function (Handle, UDate, inout Error) ucal_setMillis; 00601 void function (Handle, uint, uint, uint, inout Error) ucal_setDate; 00602 void function (Handle, uint, uint, uint, uint, uint, uint, inout Error) ucal_setDateTime; 00603 byte function (Handle, Handle) ucal_equivalentTo; 00604 void function (Handle, uint, uint, inout Error) ucal_add; 00605 void function (Handle, uint, uint, inout Error) ucal_roll; 00606 uint function (Handle, uint, inout Error) ucal_get; 00607 void function (Handle, uint, uint) ucal_set; 00608 byte function (Handle, uint) ucal_isSet; 00609 void function (Handle, uint) ucal_clearField; 00610 void function (Handle) ucal_clear; 00611 uint function (Handle, uint, uint, inout Error) ucal_getLimit; 00612 void function (Handle, wchar*, uint, inout Error) ucal_setTimeZone; 00613 byte function (Handle, uint) ucal_inDaylightTime; 00614 uint function (Handle, uint) ucal_getAttribute; 00615 void function (Handle, uint, uint) ucal_setAttribute; 00616 uint function (Handle, uint, char*, wchar*, uint, inout Error) ucal_getTimeZoneDisplayName; 00617 } 00618 00619 /*********************************************************************** 00620 00621 ***********************************************************************/ 00622 00623 static FunctionLoader.Bind[] targets = 00624 [ 00625 {cast(void**) &ucal_open, "ucal_open"}, 00626 {cast(void**) &ucal_close, "ucal_close"}, 00627 {cast(void**) &ucal_getNow, "ucal_getNow"}, 00628 {cast(void**) &ucal_getMillis, "ucal_getMillis"}, 00629 {cast(void**) &ucal_setMillis, "ucal_setMillis"}, 00630 {cast(void**) &ucal_setDate, "ucal_setDate"}, 00631 {cast(void**) &ucal_setDateTime, "ucal_setDateTime"}, 00632 {cast(void**) &ucal_equivalentTo, "ucal_equivalentTo"}, 00633 {cast(void**) &ucal_add, "ucal_add"}, 00634 {cast(void**) &ucal_roll, "ucal_roll"}, 00635 {cast(void**) &ucal_get, "ucal_get"}, 00636 {cast(void**) &ucal_set, "ucal_set"}, 00637 {cast(void**) &ucal_clearField, "ucal_clearField"}, 00638 {cast(void**) &ucal_clear, "ucal_clear"}, 00639 {cast(void**) &ucal_getLimit, "ucal_getLimit"}, 00640 {cast(void**) &ucal_setTimeZone, "ucal_setTimeZone"}, 00641 {cast(void**) &ucal_inDaylightTime, "ucal_inDaylightTime"}, 00642 {cast(void**) &ucal_getAttribute, "ucal_getAttribute"}, 00643 {cast(void**) &ucal_setAttribute, "ucal_setAttribute"}, 00644 {cast(void**) &ucal_isSet, "ucal_isSet"}, 00645 {cast(void**) &ucal_getTimeZoneDisplayName, "ucal_getTimeZoneDisplayName"}, 00646 ]; 00647 00648 /*********************************************************************** 00649 00650 ***********************************************************************/ 00651 00652 static this () 00653 { 00654 library = FunctionLoader.bind (icuin, targets); 00655 } 00656 00657 /*********************************************************************** 00658 00659 ***********************************************************************/ 00660 00661 static ~this () 00662 { 00663 FunctionLoader.unbind (library); 00664 } 00665 00666 }