[SalesForce] Salesforce timezone issue

Hi guys we have a problem with DST (Daylight Saving time)

We show the time in a Visual Force interface according to the time zone of the logged in user.

However in the Salesforce objects we are storing the time in GMT. We did this because this will support the display even after users change the timezone settings. Also schedule context will run as System and will take system timezone when running. (Not users time zone).

But now the problem is it'll run according to the GMT time not the local time. That is why user had the problem for Brussels timezone.

EG:

When scheduled before 28-Oct-2012

Schedule time in local (Brussels) – 15:00
Schedule time in GMT – 13.00

When running before 28-Oct-2012
Schedule time in local (Brussels) – 15:00
Schedule time in GMT – 13.00

When running after 28-Oct-2012
Schedule time in local (Brussels) – 14:00
Schedule time in GMT – 13.00

I can't think of an logic to support this. Any idea?

Best Answer

So I've written logic to calculate timezone offsets as an adaptation of some Apex code I found online.

This was for a similar problem where I was calling out with a date/time to webservice that was expecting GMT and was reconverting the values that SFDC was sending after they arrived assuming they were GMT (while I was still using a standard SFDC component).

It took a while, and you might want to modify it, but it includes European timezones.

This isn't a complete set, but is based on the TZ_database on wikipedia.

Hopefully this gets you going in the right direction as far as setting your dates/times.

To use, input the target timezone you want the offset from GMT for, and than you can add that value back to your time input value in hours to get the correct offset for time based on daylight savings time

     public static Integer getTZOffset(String targetTimezone) {

      Map<String, Integer[]> tzSIDKeys = getTZSidKeys();

      Date[] dstDatesNow = getDSTDates(System.Today().year());
      Integer UsersTZOffset = 0;

      if (tzSIDKeys.get(targetTimezone) != null) {
         if (System.Today() >= dstDatesNow[0] && System.Today() <= dstDatesNow[1]) UsersTZOffset = tzSIDKeys.get(targetTimezone)[1];
         else UsersTZOffset = tzSIDKeys.get(targetTimezone)[0];
      }
      return UsersTZOffset;
      }

        /* -------------------------------------------------------------------------------------
       * Returns a date Collection of Start/End dates for US Daylight Saving Time
       * for the specified year.
       *
       * Based on code from: http://www.webexhibits.org/daylightsaving/b2.html
       * ------------------------------------------------------------------------------------- */

     public static Date[] getDSTDates(Integer theYear) {
          Long thisYear;
          Long AprilDate;
          Long OctoberDate;
          Long MarchDate;
          Long NovemberDate;
          Long longSeven = 7;
          thisYear = Math.round(theYear);

      AprilDate = Math.mod(2+6 * thisYear - Math.floor(thisYear / 4).longValue(), longSeven) + 1;
      OctoberDate=  Math.mod(31-( Math.floor(thisYear * 5 / 4).longValue() + 1), longSeven);

      MarchDate = 14 - Math.mod(Math.floor(1 + thisYear * 5 / 4).LongValue(), longSeven);
      NovemberDate = 7 - Math.mod(Math.floor (1 + thisYear * 5 / 4).LongValue(), longSeven);

      string startDate = (thisYear > 2006 ? ('03/'+MarchDate) : ('04/'+AprilDate)) + '/' + thisYear;
      string endDate = (thisYear > 2006 ? ('11/'+NovemberDate):('10/'+OctoberDate))+ '/' + thisYear;

      Date[] rtnDates = new List<Date>();
      rtnDates.add(Date.parse(startDate));
      rtnDates.add(Date.parse(endDate));
      return rtnDates;
   }

   public static Map<String, Integer[]> getTZSidKeys() {
      Map<String, Integer[]> tzSIDKeys = new Map<String, Integer[]>();
      tzSIDKeys.put('America/Adak', new Integer[]{-10, -9});
      tzSIDKeys.put('America/Anchorage', new Integer[]{-9, -8});
      tzSIDKeys.put('America/Anguilla', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Antigua', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Araguaina', new Integer[]{-3, -3});// 5

      tzSIDKeys.put('America/Argentina/Buenos_Aires', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Catamarca', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/ComodRivadavia', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Cordoba', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Jujuy', new Integer[]{-3, -3}); //10

      tzSIDKeys.put('America/Argentina/La_Rioja', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Mendoza', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Rio_Gallegos', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Salta', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/San_Juan', new Integer[]{-3, -3}); //15

      tzSIDKeys.put('America/Argentina/San_Luis', new Integer[]{-3, -3}); 
      tzSIDKeys.put('America/Argentina/Tucuman', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Argentina/Ushuaia', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Aruba', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Asuncion', new Integer[]{-4, -3}); //20


      tzSIDKeys.put('America/Atikokan', new Integer[]{-5, -5});
      tzSIDKeys.put('America/Atka', new Integer[]{-10, -9});
      tzSIDKeys.put('America/Bahia', new Integer[]{-3, -2});
      tzSIDKeys.put('America/Bahia_Banderas', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Barbados', new Integer[]{-4, -4}); //25

      tzSIDKeys.put('America/Belem', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Belize', new Integer[]{-6, -6});
      tzSIDKeys.put('America/Blanc-Sablon', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Boa_Vista', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Bogota', new Integer[]{-5, -5});

      tzSIDKeys.put('America/Boise', new Integer[]{-7, -6});
      tzSIDKeys.put('America/Buenos_Aires', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Cambridge_Bay', new Integer[]{-7, -6});
      tzSIDKeys.put('America/Campo_Grande', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Cancun', new Integer[]{-6, -5});

    //  tzSIDKeys.put('America/Caracas', new Integer[]{-4.5, -4.5});
      tzSIDKeys.put('America/Catamarca', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Cayenne', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Cayman', new Integer[]{-5, -5});
      tzSIDKeys.put('America/Chicago', new Integer[]{-6, -5});

      tzSIDKeys.put('America/Chihuahua', new Integer[]{-7, -6});
      tzSIDKeys.put('America/Coral_Harbour', new Integer[]{-5, -5});
      tzSIDKeys.put('America/Cordoba', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Costa_Rica', new Integer[]{-6, -6});
      tzSIDKeys.put('America/Creston', new Integer[]{-7, -7});

      tzSIDKeys.put('America/Cuiaba', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Curacao', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Danmarkshavn', new Integer[]{0, 0});
      tzSIDKeys.put('America/Dawson', new Integer[]{-8, -7});
      tzSIDKeys.put('America/Dawson_Creek', new Integer[]{-7, -7});

      tzSIDKeys.put('America/Denver', new Integer[]{-7, -6});
      tzSIDKeys.put('America/Detroit', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Dominica', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Edmonton', new Integer[]{-7, -6});
      tzSIDKeys.put('America/Eirunepe', new Integer[]{-4, -4});

      tzSIDKeys.put('America/El_Salvador', new Integer[]{-6, -6});
      tzSIDKeys.put('America/Ensenada', new Integer[]{-8, -7});
      tzSIDKeys.put('America/Fort_Wayne', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Fortaleza', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Glace_Bay', new Integer[]{-4, -3});

      tzSIDKeys.put('America/Godthab', new Integer[]{-3, -2});
      tzSIDKeys.put('America/Goose_Bay', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Grand_Turk', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Grenada', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Guadeloupe', new Integer[]{-4, -4});

      tzSIDKeys.put('America/Guayaquil', new Integer[]{-5, -5});
      tzSIDKeys.put('America/Guyana', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Halifax', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Havana', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Hermosillo', new Integer[]{-7, -7});

      tzSIDKeys.put('America/Indiana/Indianapolis', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Indiana/Knox', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Indiana/Marengo', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Indiana/Petersburg', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Indiana/Tell_City', new Integer[]{-6, -5});

      tzSIDKeys.put('America/Indiana/Vevay', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Indiana/Vincennes', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Indiana/Winamac', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Indianapolis', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Inuvik', new Integer[]{-7, -6});

      tzSIDKeys.put('America/Iqaluit', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Jamaica', new Integer[]{-5, -5});
      tzSIDKeys.put('America/Jujuy', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Juneau', new Integer[]{-9, -8});
      tzSIDKeys.put('America/Kentucky/Louisville', new Integer[]{-5, -4});

      tzSIDKeys.put('America/Kentucky/Monticello', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Knox_IN', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Kralendijk', new Integer[]{-4, -4});
      tzSIDKeys.put('America/La_Paz', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Lima', new Integer[]{-5, -5});

      tzSIDKeys.put('America/Los_Angeles', new Integer[]{-8, -7});
      tzSIDKeys.put('America/Louisville', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Lower_Princes', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Maceio', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Managua', new Integer[]{-6, -6});

      tzSIDKeys.put('America/Manaus', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Marigot', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Martinique', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Matamoros', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Mazatlan', new Integer[]{-7, -6});

      tzSIDKeys.put('America/Mendoza', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Menominee', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Merida', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Metlakatla', new Integer[]{-8, -8});
      tzSIDKeys.put('America/Mexico_City', new Integer[]{-6, -5});

      tzSIDKeys.put('America/Miquelon', new Integer[]{-3, -2});
      tzSIDKeys.put('America/Moncton', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Monterrey', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Montevideo', new Integer[]{-3, -2});
      tzSIDKeys.put('America/Montreal', new Integer[]{-5, -4});

      tzSIDKeys.put('America/Montserrat', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Nassau', new Integer[]{-5, -4});
      tzSIDKeys.put('America/New_York', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Nipigon', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Nome', new Integer[]{-9, -8});

      tzSIDKeys.put('America/Noronha', new Integer[]{-2, -2});
      tzSIDKeys.put('America/North_Dakota/Beulah', new Integer[]{-6, -5});
      tzSIDKeys.put('America/North_Dakota/Center', new Integer[]{-6, -5});
      tzSIDKeys.put('America/North_Dakota/New_Salem', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Ojinaga', new Integer[]{-7, -6});

      tzSIDKeys.put('America/Panama', new Integer[]{-5, -5});
      tzSIDKeys.put('America/Pangnirtung', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Paramaribo', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Phoenix', new Integer[]{-7, -7});
      tzSIDKeys.put('America/Port_of_Spain', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Port-au-Prince', new Integer[]{-5, -4});

      tzSIDKeys.put('America/Porto_Acre', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Porto_Velho', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Puerto_Rico', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Rainy_River', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Rankin_Inlet', new Integer[]{-6, -5});

      tzSIDKeys.put('America/Recife', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Regina', new Integer[]{-6, -6});
      tzSIDKeys.put('America/Resolute', new Integer[]{-6, -5});
      tzSIDKeys.put('America/Rio_Branco', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Rosario', new Integer[]{-3, -3});

      tzSIDKeys.put('America/Santa_Isabel', new Integer[]{-8, -7});
      tzSIDKeys.put('America/Santarem', new Integer[]{-3, -3});
      tzSIDKeys.put('America/Santiago', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Santo_Domingo', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Sao_Paulo', new Integer[]{-3, -2});

      tzSIDKeys.put('America/Scoresbysund', new Integer[]{-1, 0});
      tzSIDKeys.put('America/Shiprock', new Integer[]{-7, -6});
      tzSIDKeys.put('America/Sitka', new Integer[]{-9, -8});
      tzSIDKeys.put('America/St_Barthelemy', new Integer[]{-4, -4});
      //tzSIDKeys.put('America/St_Johns', new Integer[]{-3.5, -2.5});

      tzSIDKeys.put('America/St_Kitts', new Integer[]{-4, -4});
      tzSIDKeys.put('America/St_Lucia', new Integer[]{-4, -4});
      tzSIDKeys.put('America/St_Thomas', new Integer[]{-4, -4});
      tzSIDKeys.put('America/St_Vincent', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Swift_Current', new Integer[]{-6, -6});

      tzSIDKeys.put('America/Tegucigalpa', new Integer[]{-6, -6});
      tzSIDKeys.put('America/Thule', new Integer[]{-4, -3});
      tzSIDKeys.put('America/Thunder_Bay', new Integer[]{-5, -4});
      tzSIDKeys.put('America/Tijuana', new Integer[]{-8,-7});
      tzSIDKeys.put('America/Toronto', new Integer[]{-5, -4});

      tzSIDKeys.put('America/Tortola', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Vancouver', new Integer[]{-8, -7});
      tzSIDKeys.put('America/Virgin', new Integer[]{-4, -4});
      tzSIDKeys.put('America/Whitehorse', new Integer[]{-8, -7});
      tzSIDKeys.put('America/Winnipeg', new Integer[]{-6, -5}); 
      tzSIDKeys.put('America/Yakutat', new Integer[]{-9, -8});     
      tzSIDKeys.put('America/Yellowknife', new Integer[]{-7, -6});

      tzSIDKeys.put('Europe/Amsterdam', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Andorra', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Athens', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Belfast', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Belgrade', new Integer[]{1, 2});

      tzSIDKeys.put('Europe/Bratislava', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Brussels', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Bucharest', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Budapest', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Chisinau', new Integer[]{2, 3});

      tzSIDKeys.put('Europe/Copenhagen', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Dublin', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Gibraltar', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Guernsey', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Helsinki', new Integer[]{2, 3});

      tzSIDKeys.put('Europe/Isle_of_Man', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Istanbul', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Jersey', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Kaliningrad', new Integer[]{3, 3});
      tzSIDKeys.put('Europe/Kiev', new Integer[]{2, 3});

      tzSIDKeys.put('Europe/Lisbon', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Ljubljana', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/London', new Integer[]{0, 1});
      tzSIDKeys.put('Europe/Luxembourg', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Kaliningrad', new Integer[]{3, 3});

      tzSIDKeys.put('Europe/Madrid', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Malta', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Mariehamn', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Minsk', new Integer[]{3, 3});
      tzSIDKeys.put('Europe/Monaco', new Integer[]{1, 2});

      tzSIDKeys.put('Europe/Moscow', new Integer[]{4, 4});
      tzSIDKeys.put('Europe/Nicosia', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Oslo', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Paris', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Podgorica', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Prague', new Integer[]{1, 2});

      tzSIDKeys.put('Europe/Prague', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Rome', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Samara', new Integer[]{4, 4});
      tzSIDKeys.put('Europe/San_Marino', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Sarajevo', new Integer[]{1, 2});

      tzSIDKeys.put('Europe/Simferopol', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Skopje', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Sofia', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Stockholm', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Tallinn', new Integer[]{2, 3});

      tzSIDKeys.put('Europe/Tirane', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Tiraspol', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Uzhgorod', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Vaduz', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Vatican', new Integer[]{1, 2});

      tzSIDKeys.put('Europe/Vienna', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Vilnius', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Volgograd', new Integer[]{4, 4});
      tzSIDKeys.put('Europe/Warsaw', new Integer[]{1, 2});
      tzSIDKeys.put('Europe/Zagreb', new Integer[]{1, 2});

      tzSIDKeys.put('Europe/Zaporozhye', new Integer[]{2, 3});
      tzSIDKeys.put('Europe/Zurich', new Integer[]{1, 2});

      return tzSIDKeys;
   }