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