1a10cf76eSAxel Dörfler /* 24ae5a452SAdrien Destugues * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. 353d9356eSStephan Aßmus * Distributed under the terms of the MIT License. 453d9356eSStephan Aßmus * 553d9356eSStephan Aßmus * Authors: 600826781SKarsten Heimrich * Mike Berg <mike@berg-net.us> 753d9356eSStephan Aßmus * Julun <host.haiku@gmx.de> 8310930fdSStephan Aßmus * Philippe Saint-Pierre <stpere@gmail.com> 94ae5a452SAdrien Destugues * Adrien Destugues <pulkomandy@pulkomandy.ath.cx> 1099d2aa98SOliver Tappe * Oliver Tappe <zooey@hirschkaefer.de> 1153d9356eSStephan Aßmus */ 1242b3a11fSStephan Aßmus 13a10cf76eSAxel Dörfler 1442b3a11fSStephan Aßmus #include "ZoneView.h" 15a10cf76eSAxel Dörfler 16317bd7ddSAxel Dörfler #include <stdlib.h> 1742b3a11fSStephan Aßmus 1838ac8defSOliver Tappe #include <new> 1938ac8defSOliver Tappe 2038ac8defSOliver Tappe #include <AutoDeleter.h> 2142b3a11fSStephan Aßmus #include <Button.h> 2299d2aa98SOliver Tappe #include <Collator.h> 23a10cf76eSAxel Dörfler #include <Directory.h> 24a10cf76eSAxel Dörfler #include <Entry.h> 2585b54438SOliver Tappe #include <File.h> 26a10cf76eSAxel Dörfler #include <FindDirectory.h> 2742b3a11fSStephan Aßmus #include <ListItem.h> 284ae5a452SAdrien Destugues #include <Locale.h> 2938ac8defSOliver Tappe #include <MutableLocaleRoster.h> 304ae5a452SAdrien Destugues #include <OutlineListView.h> 3185b54438SOliver Tappe #include <Path.h> 32a10cf76eSAxel Dörfler #include <ScrollView.h> 33a10cf76eSAxel Dörfler #include <StorageDefs.h> 34a10cf76eSAxel Dörfler #include <String.h> 354ae5a452SAdrien Destugues #include <TimeZone.h> 36a10cf76eSAxel Dörfler #include <View.h> 37310930fdSStephan Aßmus #include <Window.h> 38a10cf76eSAxel Dörfler 39317bd7ddSAxel Dörfler #include <syscalls.h> 40a10cf76eSAxel Dörfler 4138ac8defSOliver Tappe #include <unicode/datefmt.h> 4238ac8defSOliver Tappe #include <unicode/utmscale.h> 4338ac8defSOliver Tappe #include <ICUWrapper.h> 4438ac8defSOliver Tappe 45317bd7ddSAxel Dörfler #include "TimeMessages.h" 464ae5a452SAdrien Destugues #include "TimeZoneListItem.h" 47317bd7ddSAxel Dörfler #include "TZDisplay.h" 48317bd7ddSAxel Dörfler #include "TimeWindow.h" 49a10cf76eSAxel Dörfler 50a10cf76eSAxel Dörfler 5134a79bffSOliver Tappe using BPrivate::gMutableLocaleRoster; 5238ac8defSOliver Tappe using BPrivate::ObjectDeleter; 5399d2aa98SOliver Tappe 5499d2aa98SOliver Tappe 5585b69a94SKarsten Heimrich TimeZoneView::TimeZoneView(BRect frame) 5699d2aa98SOliver Tappe : 5799d2aa98SOliver Tappe BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP), 5838ac8defSOliver Tappe fCurrentZoneItem(NULL), 5938ac8defSOliver Tappe fOldZoneItem(NULL), 6099d2aa98SOliver Tappe fInitialized(false) 61a10cf76eSAxel Dörfler { 626d6408d6SOliver Tappe _InitView(); 63a10cf76eSAxel Dörfler } 64a10cf76eSAxel Dörfler 65a10cf76eSAxel Dörfler 66310930fdSStephan Aßmus bool 67310930fdSStephan Aßmus TimeZoneView::CheckCanRevert() 68310930fdSStephan Aßmus { 6938ac8defSOliver Tappe return fCurrentZoneItem != fOldZoneItem; 70310930fdSStephan Aßmus } 71310930fdSStephan Aßmus 72310930fdSStephan Aßmus 73310930fdSStephan Aßmus void 74310930fdSStephan Aßmus TimeZoneView::_Revert() 75310930fdSStephan Aßmus { 7638ac8defSOliver Tappe fCurrentZoneItem = fOldZoneItem; 77310930fdSStephan Aßmus 7838ac8defSOliver Tappe if (fCurrentZoneItem != NULL) { 7938ac8defSOliver Tappe int32 currentZoneIndex = fZoneList->IndexOf(fCurrentZoneItem); 8038ac8defSOliver Tappe fZoneList->Select(currentZoneIndex); 8138ac8defSOliver Tappe } else 8238ac8defSOliver Tappe fZoneList->DeselectAll(); 8338ac8defSOliver Tappe fZoneList->ScrollToSelection(); 844ae5a452SAdrien Destugues 8538ac8defSOliver Tappe _SetSystemTimeZone(); 8638ac8defSOliver Tappe _UpdatePreview(); 8738ac8defSOliver Tappe _UpdateCurrent(); 88310930fdSStephan Aßmus } 89310930fdSStephan Aßmus 90310930fdSStephan Aßmus 9185b69a94SKarsten Heimrich TimeZoneView::~TimeZoneView() 92a10cf76eSAxel Dörfler { 93a10cf76eSAxel Dörfler } 94a10cf76eSAxel Dörfler 95a10cf76eSAxel Dörfler 96a10cf76eSAxel Dörfler void 9785b69a94SKarsten Heimrich TimeZoneView::AttachedToWindow() 98a10cf76eSAxel Dörfler { 99a10cf76eSAxel Dörfler if (Parent()) 100a10cf76eSAxel Dörfler SetViewColor(Parent()->ViewColor()); 101a10cf76eSAxel Dörfler 10285b69a94SKarsten Heimrich if (!fInitialized) { 10385b69a94SKarsten Heimrich fInitialized = true; 10485b69a94SKarsten Heimrich 10542b3a11fSStephan Aßmus fSetZone->SetTarget(this); 10638ac8defSOliver Tappe fZoneList->SetTarget(this); 10742b3a11fSStephan Aßmus 108a10cf76eSAxel Dörfler // update displays 1094ae5a452SAdrien Destugues int32 czone = 0; 11038ac8defSOliver Tappe if (fCurrentZoneItem != NULL) { 11138ac8defSOliver Tappe czone = fZoneList->IndexOf(fCurrentZoneItem); 112310930fdSStephan Aßmus } else { 1134ae5a452SAdrien Destugues // TODO : else, select ??! 11438ac8defSOliver Tappe fCurrentZoneItem = (TimeZoneListItem*)fZoneList->ItemAt(0); 1154ae5a452SAdrien Destugues } 1164ae5a452SAdrien Destugues 11738ac8defSOliver Tappe fZoneList->Select(czone); 1184ae5a452SAdrien Destugues 11938ac8defSOliver Tappe fZoneList->ScrollToSelection(); 12038ac8defSOliver Tappe fCurrent->SetText(fCurrentZoneItem->Text()); 121a10cf76eSAxel Dörfler } 12238ac8defSOliver Tappe fZoneList->ScrollToSelection(); 123a10cf76eSAxel Dörfler } 124a10cf76eSAxel Dörfler 125a10cf76eSAxel Dörfler 126a10cf76eSAxel Dörfler void 12785b69a94SKarsten Heimrich TimeZoneView::MessageReceived(BMessage* message) 128a10cf76eSAxel Dörfler { 129a10cf76eSAxel Dörfler switch (message->what) { 130a10cf76eSAxel Dörfler case B_OBSERVER_NOTICE_CHANGE: 131317bd7ddSAxel Dörfler { 132317bd7ddSAxel Dörfler int32 change; 133a10cf76eSAxel Dörfler message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change); 134a10cf76eSAxel Dörfler switch(change) { 135a10cf76eSAxel Dörfler case H_TM_CHANGED: 1366d6408d6SOliver Tappe _UpdateDateTime(message); 137a10cf76eSAxel Dörfler break; 138a10cf76eSAxel Dörfler 139a10cf76eSAxel Dörfler default: 140a10cf76eSAxel Dörfler BView::MessageReceived(message); 141a10cf76eSAxel Dörfler break; 142a10cf76eSAxel Dörfler } 143a10cf76eSAxel Dörfler break; 144317bd7ddSAxel Dörfler } 145317bd7ddSAxel Dörfler 146a10cf76eSAxel Dörfler case H_SET_TIME_ZONE: 147310930fdSStephan Aßmus { 14838ac8defSOliver Tappe _SetSystemTimeZone(); 149310930fdSStephan Aßmus ((TTimeWindow*)Window())->SetRevertStatus(); 150310930fdSStephan Aßmus break; 151310930fdSStephan Aßmus } 152310930fdSStephan Aßmus 153310930fdSStephan Aßmus case kMsgRevert: 154310930fdSStephan Aßmus _Revert(); 155a10cf76eSAxel Dörfler break; 156a10cf76eSAxel Dörfler 157a10cf76eSAxel Dörfler case H_CITY_CHANGED: 15838ac8defSOliver Tappe _UpdatePreview(); 159a10cf76eSAxel Dörfler break; 160a10cf76eSAxel Dörfler 161a10cf76eSAxel Dörfler default: 162a10cf76eSAxel Dörfler BView::MessageReceived(message); 163a10cf76eSAxel Dörfler break; 164a10cf76eSAxel Dörfler } 165a10cf76eSAxel Dörfler } 166a10cf76eSAxel Dörfler 167a10cf76eSAxel Dörfler 168a10cf76eSAxel Dörfler void 1696d6408d6SOliver Tappe TimeZoneView::_UpdateDateTime(BMessage* message) 170a10cf76eSAxel Dörfler { 17138ac8defSOliver Tappe // only need to update once every minute 17242b3a11fSStephan Aßmus int32 minute; 17338ac8defSOliver Tappe if (message->FindInt32("minute", &minute) == B_OK) { 17438ac8defSOliver Tappe if (fLastUpdateMinute != minute) { 17538ac8defSOliver Tappe _UpdateCurrent(); 17638ac8defSOliver Tappe _UpdatePreview(); 177a10cf76eSAxel Dörfler 17838ac8defSOliver Tappe fLastUpdateMinute = minute; 179a10cf76eSAxel Dörfler } 180a10cf76eSAxel Dörfler } 181a10cf76eSAxel Dörfler } 182a10cf76eSAxel Dörfler 183a10cf76eSAxel Dörfler 184a10cf76eSAxel Dörfler void 1856d6408d6SOliver Tappe TimeZoneView::_InitView() 186a10cf76eSAxel Dörfler { 18742b3a11fSStephan Aßmus // left side 18842b3a11fSStephan Aßmus BRect frameLeft(Bounds()); 18985b69a94SKarsten Heimrich frameLeft.right = frameLeft.Width() / 2.0; 19042b3a11fSStephan Aßmus frameLeft.InsetBy(10.0f, 10.0f); 191a10cf76eSAxel Dörfler 192a10cf76eSAxel Dörfler // City Listing 19338ac8defSOliver Tappe fZoneList = new BOutlineListView(frameLeft, "cityList", 1944ae5a452SAdrien Destugues B_SINGLE_SELECTION_LIST); 19538ac8defSOliver Tappe fZoneList->SetSelectionMessage(new BMessage(H_CITY_CHANGED)); 19638ac8defSOliver Tappe fZoneList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE)); 197a10cf76eSAxel Dörfler 1986d6408d6SOliver Tappe _BuildRegionMenu(); 1994ae5a452SAdrien Destugues 20038ac8defSOliver Tappe BScrollView* scrollList = new BScrollView("scrollList", fZoneList, 20142b3a11fSStephan Aßmus B_FOLLOW_ALL, 0, false, true); 202a10cf76eSAxel Dörfler AddChild(scrollList); 203a10cf76eSAxel Dörfler 20442b3a11fSStephan Aßmus // right side 20542b3a11fSStephan Aßmus BRect frameRight(Bounds()); 20685b69a94SKarsten Heimrich frameRight.left = frameRight.Width() / 2.0; 20742b3a11fSStephan Aßmus frameRight.InsetBy(10.0f, 10.0f); 20842b3a11fSStephan Aßmus frameRight.top = frameLeft.top; 209a10cf76eSAxel Dörfler 210a10cf76eSAxel Dörfler // Time Displays 21185b69a94SKarsten Heimrich fCurrent = new TTZDisplay(frameRight, "currentTime", "Current time:"); 21242b3a11fSStephan Aßmus AddChild(fCurrent); 21342b3a11fSStephan Aßmus fCurrent->ResizeToPreferred(); 214a10cf76eSAxel Dörfler 21585b69a94SKarsten Heimrich frameRight.top = fCurrent->Frame().bottom + 10.0; 21685b69a94SKarsten Heimrich fPreview = new TTZDisplay(frameRight, "previewTime", "Preview time:"); 21742b3a11fSStephan Aßmus AddChild(fPreview); 21842b3a11fSStephan Aßmus fPreview->ResizeToPreferred(); 219a10cf76eSAxel Dörfler 220a10cf76eSAxel Dörfler // set button 2219c1a9b92SAdrien Destugues fSetZone = new BButton(frameRight, "setTimeZone", "Set time zone", 22285b69a94SKarsten Heimrich new BMessage(H_SET_TIME_ZONE)); 22342b3a11fSStephan Aßmus AddChild(fSetZone); 22442b3a11fSStephan Aßmus fSetZone->SetEnabled(false); 22542b3a11fSStephan Aßmus fSetZone->ResizeToPreferred(); 226a10cf76eSAxel Dörfler 22742b3a11fSStephan Aßmus fSetZone->MoveTo(frameRight.right - fSetZone->Bounds().Width(), 22842b3a11fSStephan Aßmus scrollList->Frame().bottom - fSetZone->Bounds().Height()); 229a10cf76eSAxel Dörfler } 230a10cf76eSAxel Dörfler 231a10cf76eSAxel Dörfler 232a10cf76eSAxel Dörfler void 2336d6408d6SOliver Tappe TimeZoneView::_BuildRegionMenu() 234a10cf76eSAxel Dörfler { 23538ac8defSOliver Tappe BTimeZone defaultTimeZone = NULL; 23699d2aa98SOliver Tappe be_locale_roster->GetDefaultTimeZone(&defaultTimeZone); 23799d2aa98SOliver Tappe 23899d2aa98SOliver Tappe // Get a list of countries and, for each country, get all the timezones and 23999d2aa98SOliver Tappe // AddUnder() them (only if there are multiple ones). 24099d2aa98SOliver Tappe // Finally expand the current country and highlight the active TZ. 241a10cf76eSAxel Dörfler 2424ae5a452SAdrien Destugues BMessage countryList; 2434ae5a452SAdrien Destugues be_locale_roster->GetAvailableCountries(&countryList); 244a10cf76eSAxel Dörfler 2454ae5a452SAdrien Destugues BString countryCode; 2464ae5a452SAdrien Destugues for (int i = 0; countryList.FindString("countries", i, &countryCode) 2474ae5a452SAdrien Destugues == B_OK; i++) { 2484ae5a452SAdrien Destugues BCountry country("", countryCode); 2494ae5a452SAdrien Destugues BString fullName; 25038ac8defSOliver Tappe country.GetName(fullName); 251a10cf76eSAxel Dörfler 2524ae5a452SAdrien Destugues // Now list the timezones for this country 2534ae5a452SAdrien Destugues BList tzList; 254a10cf76eSAxel Dörfler 25599d2aa98SOliver Tappe BTimeZone* timeZone; 2564ae5a452SAdrien Destugues TimeZoneListItem* countryItem; 2574ae5a452SAdrien Destugues switch (country.GetTimeZones(tzList)) 258a10cf76eSAxel Dörfler { 2594ae5a452SAdrien Destugues case 0: 2604ae5a452SAdrien Destugues // No TZ info for this country. Sorry guys! 2614ae5a452SAdrien Destugues break; 2624ae5a452SAdrien Destugues case 1: 2634ae5a452SAdrien Destugues // Only one Timezone, no need to add it to the list 26499d2aa98SOliver Tappe timeZone = (BTimeZone*)tzList.ItemAt(0); 26599d2aa98SOliver Tappe countryItem 26699d2aa98SOliver Tappe = new TimeZoneListItem(fullName, &country, timeZone); 26738ac8defSOliver Tappe fZoneList->AddItem(countryItem); 26838ac8defSOliver Tappe if (timeZone->Code() == defaultTimeZone.Code()) 26938ac8defSOliver Tappe fCurrentZoneItem = countryItem; 2704ae5a452SAdrien Destugues break; 2714ae5a452SAdrien Destugues default: 2724ae5a452SAdrien Destugues countryItem = new TimeZoneListItem(fullName, &country, NULL); 27399d2aa98SOliver Tappe countryItem->SetExpanded(false); 27438ac8defSOliver Tappe fZoneList->AddItem(countryItem); 2754ae5a452SAdrien Destugues 2766d6408d6SOliver Tappe for (int j = 0; 2776d6408d6SOliver Tappe (timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL; 2786d6408d6SOliver Tappe j++) { 27999d2aa98SOliver Tappe TimeZoneListItem* tzItem = new TimeZoneListItem( 28099d2aa98SOliver Tappe timeZone->Name(), NULL, timeZone); 28138ac8defSOliver Tappe fZoneList->AddUnder(tzItem, countryItem); 28238ac8defSOliver Tappe if (timeZone->Code() == defaultTimeZone.Code()) 28399d2aa98SOliver Tappe { 28438ac8defSOliver Tappe fCurrentZoneItem = tzItem; 28599d2aa98SOliver Tappe countryItem->SetExpanded(true); 28699d2aa98SOliver Tappe } 28742b3a11fSStephan Aßmus } 2884ae5a452SAdrien Destugues break; 289a10cf76eSAxel Dörfler } 290a10cf76eSAxel Dörfler } 291317bd7ddSAxel Dörfler 29238ac8defSOliver Tappe // add an artifical (i.e. belongs to no country) entry for GMT/UTC 29338ac8defSOliver Tappe BTimeZone* gmtZone = new(std::nothrow) BTimeZone(BTimeZone::kNameOfGmtZone); 29438ac8defSOliver Tappe TimeZoneListItem* gmtItem 29538ac8defSOliver Tappe = new TimeZoneListItem("- GMT/UTC (Universal Time) -", NULL, gmtZone); 29638ac8defSOliver Tappe fZoneList->AddItem(gmtItem); 29738ac8defSOliver Tappe if (gmtZone->Code() == defaultTimeZone.Code()) 29838ac8defSOliver Tappe fCurrentZoneItem = gmtItem; 29999d2aa98SOliver Tappe 30038ac8defSOliver Tappe fOldZoneItem = fCurrentZoneItem; 30199d2aa98SOliver Tappe 30299d2aa98SOliver Tappe struct ListSorter { 30399d2aa98SOliver Tappe static int compare(const BListItem* first, const BListItem* second) 30499d2aa98SOliver Tappe { 30538ac8defSOliver Tappe static BCollator collator; 30638ac8defSOliver Tappe return collator.Compare(((BStringItem*)first)->Text(), 30799d2aa98SOliver Tappe ((BStringItem*)second)->Text()); 30899d2aa98SOliver Tappe } 30999d2aa98SOliver Tappe }; 31038ac8defSOliver Tappe fZoneList->SortItemsUnder(NULL, false, ListSorter::compare); 311a10cf76eSAxel Dörfler } 312a10cf76eSAxel Dörfler 313a10cf76eSAxel Dörfler 314a10cf76eSAxel Dörfler void 31538ac8defSOliver Tappe TimeZoneView::_UpdatePreview() 316a10cf76eSAxel Dörfler { 31738ac8defSOliver Tappe int32 selection = fZoneList->CurrentSelection(); 318a10cf76eSAxel Dörfler if (selection < 0) 319a10cf76eSAxel Dörfler return; 320a10cf76eSAxel Dörfler 32138ac8defSOliver Tappe TimeZoneListItem* item = (TimeZoneListItem*)fZoneList->ItemAt(selection); 32238ac8defSOliver Tappe if (!item->HasTimeZone()) 32338ac8defSOliver Tappe return; 324a10cf76eSAxel Dörfler 32538ac8defSOliver Tappe BString timeString = _FormatTime(item); 32638ac8defSOliver Tappe fPreview->SetText(item->Text()); 32738ac8defSOliver Tappe fPreview->SetTime(timeString.String()); 328a10cf76eSAxel Dörfler 32938ac8defSOliver Tappe fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0)); 330a10cf76eSAxel Dörfler } 331a10cf76eSAxel Dörfler 332a10cf76eSAxel Dörfler 333a10cf76eSAxel Dörfler void 33438ac8defSOliver Tappe TimeZoneView::_UpdateCurrent() 335a10cf76eSAxel Dörfler { 33638ac8defSOliver Tappe if (fCurrentZoneItem == NULL) 33738ac8defSOliver Tappe return; 3381855b44cSAdrien Destugues 33938ac8defSOliver Tappe BString timeString = _FormatTime(fCurrentZoneItem); 34038ac8defSOliver Tappe fCurrent->SetText(fCurrentZoneItem->Text()); 34138ac8defSOliver Tappe fCurrent->SetTime(timeString.String()); 342a10cf76eSAxel Dörfler } 343a10cf76eSAxel Dörfler 34438ac8defSOliver Tappe 34538ac8defSOliver Tappe void 34638ac8defSOliver Tappe TimeZoneView::_SetSystemTimeZone() 34738ac8defSOliver Tappe { 34838ac8defSOliver Tappe /* Set sytem timezone for all different API levels. How to do this? 34938ac8defSOliver Tappe * 1) tell locale-roster about new default timezone 35085b54438SOliver Tappe * 2) tell kernel about new timezone offset 35185b54438SOliver Tappe * 3) write new POSIX-timezone-info file 35238ac8defSOliver Tappe */ 35338ac8defSOliver Tappe 35438ac8defSOliver Tappe int32 selection = fZoneList->CurrentSelection(); 35538ac8defSOliver Tappe if (selection < 0) 35638ac8defSOliver Tappe return; 35738ac8defSOliver Tappe 35838ac8defSOliver Tappe fCurrentZoneItem = (TimeZoneListItem*)(fZoneList->ItemAt(selection)); 3590aa23047SOliver Tappe const BTimeZone& timeZone = fCurrentZoneItem->TimeZone(); 36038ac8defSOliver Tappe 36134a79bffSOliver Tappe gMutableLocaleRoster->SetDefaultTimeZone(timeZone); 36238ac8defSOliver Tappe 3637e965f50SOliver Tappe _kern_set_timezone(timeZone.OffsetFromGMT()); 36438ac8defSOliver Tappe 36585b54438SOliver Tappe BPath path; 36685b54438SOliver Tappe status_t status = find_directory(B_COMMON_SETTINGS_DIRECTORY, &path, true); 36785b54438SOliver Tappe BFile file; 36885b54438SOliver Tappe if (status == B_OK) { 369*a096bb65SOliver Tappe path.Append("libroot_timezone_info"); 37085b54438SOliver Tappe status = file.SetTo(path.Path(), 37185b54438SOliver Tappe B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); 37285b54438SOliver Tappe } 37385b54438SOliver Tappe if (status == B_OK) { 374*a096bb65SOliver Tappe const BString& timeZoneID = timeZone.Code(); 375*a096bb65SOliver Tappe file.Write(timeZoneID.String(), timeZoneID.Length()); 37685b54438SOliver Tappe file.Sync(); 37785b54438SOliver Tappe } 37885b54438SOliver Tappe 37938ac8defSOliver Tappe fSetZone->SetEnabled(false); 38038ac8defSOliver Tappe fLastUpdateMinute = -1; 38138ac8defSOliver Tappe // just to trigger updating immediately 38238ac8defSOliver Tappe } 38338ac8defSOliver Tappe 38438ac8defSOliver Tappe 38538ac8defSOliver Tappe BString 38638ac8defSOliver Tappe TimeZoneView::_FormatTime(TimeZoneListItem* zoneItem) 38738ac8defSOliver Tappe { 38838ac8defSOliver Tappe BString result; 38938ac8defSOliver Tappe 39038ac8defSOliver Tappe if (zoneItem == NULL) 39138ac8defSOliver Tappe return result; 39238ac8defSOliver Tappe 3935c3a3034SAdrien Destugues BLocale locale; 3945c3a3034SAdrien Destugues be_locale_roster->GetDefaultLocale(&locale); 395*a096bb65SOliver Tappe time_t now = time(NULL); 396*a096bb65SOliver Tappe bool rtcIsGMT; 397*a096bb65SOliver Tappe _kern_get_real_time_clock_is_gmt(&rtcIsGMT); 398*a096bb65SOliver Tappe if (!rtcIsGMT) { 399*a096bb65SOliver Tappe now -= zoneItem->OffsetFromGMT() - fCurrentZoneItem->OffsetFromGMT(); 400*a096bb65SOliver Tappe } 401*a096bb65SOliver Tappe locale.FormatTime(&result, now, false, &zoneItem->TimeZone()); 40238ac8defSOliver Tappe 40338ac8defSOliver Tappe return result; 40438ac8defSOliver Tappe } 405