/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.util; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import com.servoy.j2db.IApplication; import com.servoy.j2db.IServiceProvider; /** * This class contains utility methods for handling time zones. WC and SC need different conversions at SQLEngine level. * @see ClientManager#showStringDatesTheSameOnAllClients. */ public class TimezoneUtils { public static long convertToTimezone(long date, TimeZone sourceTimeZone, TimeZone destinationTimeZone) { if (sourceTimeZone == null || destinationTimeZone == null) return date; if (sourceTimeZone.equals(destinationTimeZone)) return date; GregorianCalendar source = new GregorianCalendar(sourceTimeZone); GregorianCalendar destination = new GregorianCalendar(destinationTimeZone); source.setTimeInMillis(date); destination.set(Calendar.YEAR, source.get(Calendar.YEAR)); destination.set(Calendar.MONTH, source.get(Calendar.MONTH)); destination.set(Calendar.DAY_OF_MONTH, source.get(Calendar.DAY_OF_MONTH)); destination.set(Calendar.HOUR_OF_DAY, source.get(Calendar.HOUR_OF_DAY)); destination.set(Calendar.MINUTE, source.get(Calendar.MINUTE)); destination.set(Calendar.SECOND, source.get(Calendar.SECOND)); destination.set(Calendar.MILLISECOND, source.get(Calendar.MILLISECOND)); if (Debug.tracing()) { Debug.trace("converting date: " + date + " to " + destination.getTimeInMillis() + " source timezone:" + sourceTimeZone + " dest: " + destinationTimeZone); } return destination.getTimeInMillis(); } public static long convertOutgoingDate(long date, TimeZone clientTimeZone, TimeZone serverTimeZone, boolean smartClient) { if (smartClient) { return convertToTimezone(date, serverTimeZone, clientTimeZone); } else { return convertToTimezone(date, clientTimeZone, serverTimeZone); } } public static Date convertIncomingDate(Date date, TimeZone clientTimeZone, TimeZone serverTimeZone, boolean smartClient) { long ms; if (smartClient) { ms = convertToTimezone(date.getTime(), clientTimeZone, serverTimeZone); } else { ms = convertToTimezone(date.getTime(), serverTimeZone, clientTimeZone); } if (date.getClass() == Timestamp.class) { return new Timestamp(ms); } if (date.getClass() == Time.class) { return new Time(ms); } if (date.getClass() == java.sql.Date.class) { return new java.sql.Date(ms); } else return new Date(ms); } public static Date getClientDate(IServiceProvider application) { try { // because of the fact that in non-SC dates format is applied on server timezone, if clients are set to display dates according // to their timezone info, non-SC dates are shifted by the time zone difference when used in JS; see ClientManager.getConversionTimezone()... // so simle new Date() in this case would really be wrong (unfortunately this problem also manifests when using simple new Date() as JS object...) if (application instanceof IApplication && Utils.isSwingClient(((IApplication)application).getApplicationType())) { return new Date(); } else { return new Date(TimezoneUtils.convertToTimezone(System.currentTimeMillis(), application.getTimeZone(), TimeZone.getDefault())); } } catch (Exception e) { // should never happen (remote exception for non RMI client) Debug.warn(e); return new Date(); } } }