/*******************************************************************************
 * Copyright (c) 2004, 2005 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.core.data;

import java.text.ParseException;

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.TimeZone;

import java.util.Date;

import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.exception.CoreException;
import org.eclipse.birt.core.i18n.ResourceConstants;

/**
 * DateFormatISO8601 is a utility class for formatting and parsing dates
 * according to date format defined by ISO8601.
 */

public class DateFormatISO8601
{

	/**
	 * Parse a date/time string.
	 * @param source
	 * @return
	 * @throws ParseException
	 */
	public static Date parse( String source, TimeZone timeZone ) throws BirtException,
			ParseException
	{
		if ( source == null || source.trim( ).length( ) == 0 )
		{
			return null;
		}
		Date resultDate = null;
		source = cleanDate( source );
		Object simpleDateFormatter = DateFormatFactory.getPatternInstance( PatternKey.getPatterKey( source ) );
		if ( simpleDateFormatter != null )
		{
			SimpleDateFormat dateFormat = (SimpleDateFormat) simpleDateFormatter;
			TimeZone savedTimeZone = null;
			try
			{
				if ( timeZone != null )
				{
					savedTimeZone = dateFormat.getTimeZone( );
					dateFormat.setTimeZone( timeZone );
				}
				resultDate = dateFormat.parse( source );
				return resultDate;
			}
			catch ( ParseException e1 )
			{
			}
			finally
			{
				if ( savedTimeZone != null )
					dateFormat.setTimeZone( savedTimeZone );
			}
		}
		// for the String can not be parsed, throws a BirtException
		if ( resultDate == null )
		{
			throw new ParseException( "an not convert the value of " + source,
					0 );
		}

		// never access here
		return resultDate;
	}
	
	
	/**
	 * Parse a date/time string.
	 * @param source
	 * @return
	 * @throws ParseException
	 */
	public static String format( Date date ) throws BirtException
	{
		String result = null;
		if ( date == null  )
		{
			return null;
		}
		
		Object simpleDateFormatter = DateFormatFactory.getPatternInstance( PatternKey.getPatterKey( "yyyy-MM-dd HH:mm:ss.sZ" ) );
		if ( simpleDateFormatter != null )
		{
			try
			{
				result = ( (SimpleDateFormat) simpleDateFormatter ).format( date );
				return result;
			}
			catch ( Exception e1 )
			{
			}
		}
		// for the String can not be parsed, throws a BirtException
		if ( result == null )
		{
			throw new CoreException( 
					ResourceConstants.CONVERT_FAILS,
					new Object[]{
							date.toString( ), "ISO8601 Format"
					} );
		}

		// never access here
		return result;
	}
	
	/**
	 * 
	 * @param s
	 * @return
	 */
	private static String cleanDate( String s )
	{
		s = s.trim( );
		if ( s.indexOf( 'T' ) < 12 )
		{
			s = s.replaceFirst( "T", " " );
		}
		
		int zoneIndex = s.indexOf( "GMT" );
		if( zoneIndex > 0 )
		{
			return s.substring( 0, zoneIndex ).trim( );
		}
		zoneIndex = s.indexOf( 'Z' );
		if ( zoneIndex == s.length( ) - 1 )
		{
			return s.substring( 0, zoneIndex ).trim( );
		}
		zoneIndex = getZoneIndex( s );
		if ( zoneIndex > 0 )
		{
			return s.substring( 0, zoneIndex ).trim( );
		}
		
		return s;
	}

	/**
	 * 
	 * @param s
	 * @return
	 */
	private static int getZoneIndex( String s )
	{
		int index = s.indexOf( '+' );
		if ( index > 0 )
		{
			return index;
		}
		
		index = s.indexOf( '-' ); //first '-'
		if ( index > 0 )
		{
			index = s.indexOf( '-', index + 1 ); //second '-'
		}
		else
		{
			return index;
		}
		if ( index > 0 )
		{
			index = s.indexOf( '-', index + 1 ); //third '-'
		}
		else
		{
			return index;
		}
		return index;
	}
	

}

@@ -3250,24 +3250,51 @@
 , %22 %22 );
+//$NON-NLS-1$ //$NON-NLS-2$
 %0A%09%09%7D%0A%09%09%0A
 %09%09int zo
@@ -3281,24 +3281,26 @@
 S-2$%0A%09%09%7D%0A%09%09%0A
+//
 %09%09int zoneIn
@@ -3324,17 +3324,33 @@
 %22GMT%22 );
-%0A
+ //$NON-NLS-1$%0A//
 %09%09if( zo
@@ -3355,36 +3355,40 @@
 zoneIndex %3E 0 )%0A
+//
 %09%09%7B%0A
+//
 %09%09%09return s.subs
@@ -3410,38 +3410,44 @@
 ndex ).trim( );%0A
+//
 %09%09%7D%0A%09%09
+int 
 zoneIndex = s.in
@@ -3553,16 +3553,18 @@
  );%0A%09%09%7D%0A
+//
 %09%09zoneIn
@@ -3584,24 +3584,26 @@
 Index( s );%0A
+//
 %09%09if ( zoneI
@@ -3605,36 +3605,40 @@
 zoneIndex %3E 0 )%0A
+//
 %09%09%7B%0A
+//
 %09%09%09return s.subs
@@ -3664,24 +3664,26 @@
  ).trim( );%0A
+//
 %09%09%7D%0A%09%09%0A%09%09ret

Fix the bugzilla bug 245637 : timezone in datetime from Calendar picker doesn't work[10]