• No results found

Developer Story on Date-Time Handling in Time Zone unaware Scenario

N/A
N/A
Protected

Academic year: 2021

Share "Developer Story on Date-Time Handling in Time Zone unaware Scenario"

Copied!
27
0
0

Loading.... (view fulltext now)

Full text

(1)

Developer Story on “Date-Time”

Handling in Time Zone unaware

Scenario

Applies to:

Feature pack 1 for Duet Enterprise 1.0.

Summary

We often come across objects that do not understand time zone information. In other word these object treat time as absolute. For e.g. in ERP time recording objects would consider time as absolute. It would not have capability to consider 1AM-10AM (in local time) same as 6:30 – 14:30 (IST, in UTC format) and hence would lead to storage of two different set of data for the same time duration. In order to overcome this type of issue the document contains workarounds that should be implemented in your Duet Enterprise solution.

Authors: Balamuruga P and Moitra Oyshik Company: SAP Labs India

Created on: May 4, 2012

Author Bio

(2)

Table of Contents

Introduction ... 3

Why special handling for „Time zone unaware scenario‟ ... 3

Flow Diagram ... 4

Pre-requisite: Class Creation ... 5

How to enable the special handling for “Timezone unaware scenarios” ... 10

Modification of data type in generated Service Interface ... 11

Regenerate the Server Proxy ... 12

Code Changes in Implementation class ... 13

Handcraft Section ... 17

Provider Class implementation ... 17

Custom form for handling Date Types ... 19

(3)

Introduction

This document is relevant for the case where the backend RFC do not respect the time zone relevant information. Also below recommendations were not for the case which requires calendar building Blocks like Time management and Leave management scenario.

Why special handling for „Time zone unaware scenario‟

With Tooling story (BDC Browser generated code) for a case which has the date time handling, below are the problem statements:

A sales representative, who works in Bangalore (IST time zone), creates a sales order on 1st Jan 2012. Assume his manager is located in Palo Alto (PST) and his peer Sales Representative is in Japan.

Manager would see the sales order creation date as 31st December 2011 and his peer Sales Representative in Japan would see the creation date as 2nd January 2012.

Is the creation date on December 31st, or Jan 1st, or Jan 2nd? This would confuse the manager and peer colleagues.

Also in India, Diwali (the festival of lights) is celebrated on Tuesday, November 13, 2012. When colleagues start celebrating in India, it is still November 12 in Toronto. In Japan it will be already November 14. So is Diwali on November 12, 13 or 14?

Technical Consultant should be aware of the behavior of RFC. Whether the RFC respects the timezone information or not? By default, when the date-time information is passed to Gateway Addon; date-time value will be converted to GMT time zone format from the SharePoint layer. Then Gateway Addon layer will convert the received date-time value to user‟s time zone and it will be stored in database table. This time zone conversion code was generated by the BDC Browser code.

For the case where RFC does not respects the time zone information, DB table will not reflect the actual value of date-time which was entered by the user. Due to different value of date-time, it would affect various other calculations based on the existing wrong value. In this case, actual value of user entered date-time in SharePoint is expected in DB table. Values are expected to be saved without honoring the time zone. Currently there is a discrepancy in data store in SAP.

(4)

Flow Diagram

Yes

No

Tooling using BDC Browser

Handcraft Analysis on Backend RE Backend RFC respect the time zone

information

No Special Handling

required

Changes in ESR layer Section 1.3.1

Changes in Gateway Addon layer Section 1.3

Changes in Sharepoint side [ Custom Control ] Section 1.5

Approach

Ensure that data type for the date

and time attributes should

be STRING

Changes in Gateway Addon layer Section 1.4.1

(5)

Pre-requisite: Class Creation

This section is common for both Tooling and handcraft part.

Please create below class & method in the Gateway Addon system.

Class Name Class Purpose

ZIWTNG_CL_DATETIME_UTIL Class to handle the Date Time Format Conversion logic. Instantiation: Public

Method and Purpose:

GET_DATE_IN ( ) – This method converts from YYYY-MM-DDTHH:MM:SS to YYYYMMDD format

GET_TIMESTAMP_IN ( ) – This method YYYY-MM-DDTHH:MM:SS to YYYYMMDDHHMMSS format

GET_TIMESTAMP_OUT ( ) – This method converts from YYYYMMDDHHMMSS To YYYY-MM-DDTHH:MM:SS format GET_DATE_OUT ( ) – This method converts from

YYYYMMDD To YYYY-MM-DDTHH:MM:SS format

Method name: GET_DATE_IN ( ) Level: Static method

Visibility: Public

Name Operation type Type Optional

IV_DATETIME Importing STRING No

RT_DATE Returning CHAR8 No

Method name: GET_TIMESTAMP_IN ( ) Level: Static method

Visibility: Public

Name Operation type Type Optional

IV_DATETIME Importing STRING No

RT_DATETIME Returning CHAR14 No

Method name: GET_TIMESTAMP_OUT ( ) Level: Static method

Visibility: Public

Name Operation type Type Optional

IV_DATETIME Importing TIMESTAMPL No

(6)

Method name: GET_DATE_OUT ( ) Level: Static method

Visibility: Public

Name Operation type Type Optional

IV_DATETIME Importing /OSP/DT_DATE No

RT_DATETIME Returning CHAR19 No

Method name: GET_TIME_IN ( ) Level: Static method

Visibility: Public

Name Operation type Type Optional

IV_DATETIME Importing STRING No

RT_TIME Returning CHAR6 No

Method name: GET_TIME_OUT ( ) Level: Static method

Visibility: Public

Name Operation type Type Optional

IV_TIME Importing TIMS No

RT_DATETIME Returning CHAR19 No

Code Snippet for GET_DATE_IN Method

method get_date_in.

* Conversion logic

* Conversion from YYYY-MM-DDTHH:MM:SS to YYYYMMDD

data: lv_date_of_birth_full type c length 19. data: lv_date_of_birth type c length 8.

lv_date_of_birth_full = iv_datetime.

* Conversion from YYYY-MM-DDTHH:MM:SS to YYYYMMDDHHMMSS if lv_date_of_birth_full is not initial.

replace all occurrences of '-' in lv_date_of_birth_full with ''. replace all occurrences of ':' in lv_date_of_birth_full with ''. replace all occurrences of 'T' in lv_date_of_birth_full with ''. endif.

* Conversion from YYYYMMDDHHMMSS to YYYYMMDD lv_date_of_birth = lv_date_of_birth_full. rt_date = lv_date_of_birth.

(7)

Code Snippet for GET_TIMESTAMP_IN Method

method get_timestamp_in.

* Conversion logic

* Conversion from YYYY-MM-DDTHH:MM:SS to YYYYMMDDHHMMSS

data: lv_datetime_nonutc type c length 19.

lv_datetime_nonutc = iv_datetime.

if lv_datetime_nonutc is not initial.

replace all occurrences of '-' in lv_datetime_nonutc with ''. replace all occurrences of ':' in lv_datetime_nonutc with ''. replace all occurrences of 'T' in lv_datetime_nonutc with ''. endif.

rt_datetime = lv_datetime_nonutc. endmethod.

Code Snippet for GET_TIMESTAMP_OUT Method method get_timestamp_out.

* Conversion logic

* Conversion from YYYYMMDDHHMMSS To YYYY-MM-DDTHH:MM:SS data: lv_datetime type string.

data: lv_datetime_nonutc type c length 19. data: lv_length type i.

* Getting length of the datetime input lv_datetime = iv_datetime.

lv_length = strlen( iv_datetime ).

* conversion logic from 20120304050600 to 2012-03-04t05:06:00 if iv_datetime is not initial.

if lv_length ge 14.

clear: lv_datetime_nonutc.

concatenate lv_datetime+0(4) '-' lv_datetime+4(2) '-' lv_datetime+6(2) 'T' lv_datetime+8(2) ':' lv_datetime+10(2) ':' lv_datetime+12(2)

into lv_datetime_nonutc. rt_datetime = lv_datetime_nonutc. else. rt_datetime = '8900:12:31T00:00:00'. endif. else. rt_datetime = '8900:12:31T00:00:00'. endif. endmethod.

(8)

Code Snippet for GET_DATE_OUT Method

method get_date_out.

* Conversion logic

* Conversion from YYYYMMDD To YYYY-MM-DDTHH:MM:SS

data: lv_datetime type string.

data: lv_datetime_nonutc type c length 19. data: lv_length type i.

* Getting the length of the datetime input lv_datetime = iv_datetime.

lv_length = strlen( lv_datetime ).

* Conversion logic from 19901112 TO 1990-11-12T00:00:00 if lv_length ge 8.

if iv_datetime is not initial.

*convert to ISO Date Time Format YYYY-MM-DDThh:mm:ss clear: lv_datetime_nonutc.

concatenate lv_datetime+0(4) '-' lv_datetime+4(2) '-' lv_datetime+6(2) 'T00:00:00' into lv_datetime_nonutc. rt_datetime = lv_datetime_nonutc. endif. else. rt_datetime = '8900:12:31T00:00:00'. endif. if iv_datetime is initial. rt_datetime = '8900:12:31T00:00:00'. endif. endmethod.

Code Snippet for GET_TIME_IN Method

method get_time_in.

* Conversion logic

* Conversion from YYYY-MM-DDTHH:MM:SS to HHMMSS

data: lv_date_of_time_full type c length 19.

lv_date_of_time_full = iv_datetime.

* Conversion from YYYY-MM-DDTHH:MM:SS to YYYYMMDDHHMMSS if lv_date_of_time_full is not initial.

replace all occurrences of '-' in lv_date_of_time_full with ''. replace all occurrences of ':' in lv_date_of_time_full with ''.

(9)

replace all occurrences of 'T' in lv_date_of_time_full with ''. endif.

* Conversion from YYYYMMDDHHMMSS to YYYYMMDD rt_time = lv_date_of_time_full+8(6).

endmethod.

Code Snippet for GET_TIME_OUT Method

method GET_TIME_OUT.

* Conversion logic

* Conversion from YYYYMMDD To YYYY-MM-DDTHH:MM:SS

DATA: lv_datetime TYPE string.

DATA: lv_datetime_nonutc TYPE c LENGTH 19. DATA: lv_length TYPE i.

* Getting the length of the datetime input lv_datetime = iv_time.

lv_length = strlen( lv_datetime ).

* Conversion logic from 19901112 TO 1990-11-12T00:00:00 IF lv_length EQ 6.

IF iv_time IS NOT INITIAL.

*convert to ISO Date Time Format YYYY-MM-DDThh:mm:ss CLEAR: lv_datetime_nonutc.

CONCATENATE '8900-12-31T'

lv_datetime+0(2)':' lv_datetime+2(2)':' lv_datetime+4(2) INTO lv_datetime_nonutc. rt_datetime = lv_datetime_nonutc. ENDIF. ELSE. rt_datetime = '8900-12-31T00:00:00'. ENDIF. endmethod.

(10)

How to enable the special handling for “Timezone unaware scenarios”

For the above stated problem, we need a way to get the actual date-time value from the SharePoint to Gateway Addon layer.

 Identify the fields which fall in the DATETIME & DATE fields under this scenario. Let us consider DATETIME_NONUTC and DATE_OF_BIRTH as the indicative fields in the example discussed below.

 Use custom control in SharePoint UI in order to avoid the GMT time zone conversion. This control will format the user entered value to particular string format. String format will be passed to Gateway Addon.

Operations

Attributes

Date

Time

Time

Date of Birth

Query

Special handling required. Custom Form that would contain date time picker control and in the backend there should be code to populate the picker with the

data from the string parameter and vice versa. Data Type in ESR should be STRING Special handling required. Custom Form (with Time only flag) that would contain date time

picker control and in the backend there should be code to populate the picker with the data from the string parameter

and vice versa. Data Type in ESR should be

STRING

Special handling required. Custom Form (with Time only flag) that would contain date time picker control and in the backend there should be code to populate the

picker with the data from the string parameter and vice

versa. Data Type in ESR should be STRING

Read

Create

Update

Delete

No changes required No changes required No changes required

 To receive the string format value, Server proxy‟s interface data type should be of STRING. After receiving the input, format needs to be converted so that it can be passed to Gateway API.

„xsd:string‟ data type have to be set in the DATETIME_NONUTC and DATE_OF_BIRTH fields of generated web service and in addition the BDC model should also have string data type. The Date-time object (for DATETIME_NONUTC, TIME and DATE_OF_BIRTH) in the SharePoint is converted into string with format

YYYY-MM-DDTHH: MM: SS. The corresponding string format is read in the Gateway Addon layer and then

(11)

Gateway Addon to SharePoint. Gateway Addon will send the dates in string format, which is then read in SharePoint layer and converted to Date-Time object.

Following are the steps to enhance the existing functionality in Gateway Addon Layer

a) Modification of data type to „xsd:string‟ for DATETIME_NONUTC & DATE_OF_BIRTH, TIME fields in generated service interface

b) Regenerate the Server Proxy

c) Enhance code in Create, Update, Query and Read methods of WS Implementation class Modification of data type in generated Service Interface

Modification of data type has to be done in ESR system, locate the service in ESR system under the namespace where it was created. Namespace can be found with below steps

1. Go to transaction /iwtng/bdc_browser.

2. Go to menu path Tool settings ->Service settings. 3. Double click the active configuration id.

4. Namespace can found from this Service settings view.

For Query and Read operation, the output data type must have those identified fields. For Update and Create operation input data type should have those identified fields.

Below is the example for Create operation. Select the Create operation in ESR view, double click on Request Message Type, and double click on data type for IS_INPUT. It will open up the data type for input to create operation. To this data type, modify the data type to IWXString, as shown below.

DATE_OF_BIRTH, DATETIME_NONUTC and TIME fields‟ data type should be set to IWXString. Save the data type.

Follow the above steps for modifying the data type for those identified fields

Request data type for Update operation (data type corresponding to IS_INPUT)

Response data type for Query operation (data type corresponding to ET_OUTPUT)

Response data type for Read operation (data type corresponding to ES_OUTPUT) Finally save and activate all the data types.

(12)

Regenerate the Server Proxy

Once the data types have been changed, save and activate the service interface in ESR system. Re-generate the server proxy and the changed data type in sproxy transaction in Gateway Addon. The server proxy should have the changes.

(13)

Code Changes in Implementation class

For Create and Update operations, the string fields would be filled up by the SharePoint codebehind. The string values will then be converted into ABAP date and stored in backend system. For read scenario, Read and Query operations, the string fields will be filled up in Gateway Addon layer and then sent to SharePoint without time zone conversion.

The code has to be changed in the implementation class of the proxy. You can find the implementation class in the following screen.

(14)

Methods (CREATE_ZDT_PBAPOC_BLOGREQUEST & UPDATE_ZDT_PBAPOC_BLOGREQUEST) Please note down below highlighted code block. Below blocks were the generated code for the two fields DATETIME_NONUTC and DATE_OF_BIRTH. In this case, there are only two fields. Depending on the number of these kind of fields, below highlighted code block would vary in numbers and also in the

positioning of these code blocks in your method. Hence the suggestion for removing the below code block is to look for the code block which is identical as below highlighted blocks and comment or delete the code blocks.

(15)

Code Snippet for DATETIME_NONUTC and DATE_OF_BIRTH [ONLY for Create and Update method]

* Comment below line

* ls_input-DATETIME_NONUTC = <ls_input>-is_input-DATETIME_NONUTC.

* From the sharepoint, we get the input(lv_date_of_birth_full) as * 1990-11-12T00:00:00, this needs to modified to 19901112

ls_input-date_of_birth

= ziwtng_cl_datetime_util=>get_date_in( <ls_input>-is_input-date_of_birth ).

* From the sharepoint, we get the input(lv_datetime_nonutc) as * 2012-03-04T05:06:00, this needs to modified to 20120304050600

ls_input-datetime_nonutc

= ziwtng_cl_datetime_util=>get_timestamp_in( <ls_input>-is_input-datetime_nonutc ).

* From the SharePoint, we get the input(time) as * YYYY-MM-DDTHH:MM:SS this needs to modified to HHMMSS

ls_input-time

= ziwtng_cl_datetime_util=>get_time_in( <ls_input>-is_input-time ).

Following code explains the handling in Read and Find methods of the provider class.

Methods (READ_ZDT_PBAPOC_BLOGBY_IDQUERY & FIND_ZDT_PBAPOC_BLOGBY_ELEMENT)

Please note down below highlighted code block. Below blocks were the generated code for the two fields DATETIME_NONUTC and DATE_OF_BIRTH. In this case, there are only two fields. Depending on the number of these kinds of fields, below highlighted code block would vary in numbers and also in the

positioning of these code blocks in your method. Hence the suggestion for removing the below code block is to look for the code block which is identical as below highlighted blocks and comment or delete the code blocks.

(16)

Insert the below block code.

Code Snippet for End Time [Only for Read and Query]

* Conversion logic from 20120304050600 TO 2012-03-04T05:06:00 <ls_output>-es_output-datetime_nonutc

= ziwtng_cl_datetime_util=>get_timestamp_out( ls_output-datetime_nonutc ).

* Conversion logic from 19901112 TO 1990-11-12T00:00:00 <ls_output>-es_output-date_of_birth

= ziwtng_cl_datetime_util=>get_date_out( ls_output-date_of_birth ).

* Conversion logic from HHMMSS TO YYYY-MM-DDTHH:MM:SS

<ls_output>-es_output-time = ziwtng_cl_datetime_util=>get_time_out( ls_output1-time ).

Note: As mentioned in the above sections, provider class methods have been modified. In future, if the same service interface gets regenerated, then there is a chance of losing the code which exists as part of provider class method implementations. Before the service interface gets regenerated, please do not forget to take the backup of the existing code. After regeneration, old code should be placed back

(17)

Handcraft Section

Technical Consultant should be aware of the behavior of RFC. Whether the RFC respects the timezone information or not? For the DATETIME_NONUTC & DATE_OF_BIRTH field, if the RFC does not respect the time zone, then following point should be considered.

Ensure the data type for those fields in ESR is with „xsd:string‟ data type. Provider Class implementation

1) Create the „ZIWTNG_CL_DATETIME_UTIL‟ class as mentioned in the pre-requisite section.

2) In READ & QUERY method, ensure that those fields are set to YYYY-MM-DDTHH:MM:SS format in the output parameters.

Sample code flow for READ & QUERY Method below mentioned in order to show the special handling of date-time value. Special handling has to be done only after invoking the SOAP Bridge API.

* Invoke the SOAP Bridge API to read the user’s detail

CALL METHOD /iwfnd/cl_soap_bridge=>bulk_read EXPORTING iv_request_uuid = lv_request_id iv_consumer_type_code = /iwtng/if_common_const=>gcv_consumer_type_code iv_cor_gsdo_type = lc_gsdo_user iv_exception_class_name = /iwtng/cl_global_constants=>gc_exception_class it_input = lt_user_ids IMPORTING et_output = lt_output. .

* Place the below code block after invoking the SOAP Bridge API. * Loop through output internal table for formatting the datetime

* Conversion logic from 20120304050600 TO 2012-03-04T05:06:00 <ls_output>-es_output-datetime_nonutc

= ziwtng_cl_datetime_util=>get_timestamp_out( ls_output-datetime_nonutc ).

* Conversion logic from 19901112 TO 1990-11-12T00:00:00 <ls_output>-es_output-date_of_birth

= ziwtng_cl_datetime_util=>get_date_out( ls_output-date_of_birth ).

* Conversion logic from HHMMSS TO YYYY-MM-DDTHH:MM:SS <ls_output>-es_output-time

= ziwtng_cl_datetime_util=>get_time_out( ls_output-time ).

* Conversion logic from HHMMSS TO YYYY-MM-DDTHH:MM:SS <ls_output>-es_output-time

= ziwtng_cl_datetime_util=>get_time_out( ls_output-time ).

a. In CREATE & UPDATE method, ensure to implement the format conversion logic(YYYY-MM-DDTHH:MM:SS to YYYYMMDDHHMMSS) before invoking the Gateway API.

Sample code flow for CREATE Method below mentioned in order to show the special handling of datetime value. Special handling has to be done only before invoking the SOAP Bridge API.

(18)

Code Snippet for DATETIME_NONUTC and DATE_OF_BIRTH [ONLY for Create and Update method]

DATA: lv_datetime_nonutc TYPE C LENGTH 14. DATA: lv_date_of_birth TYPE C LENGTH 8.

* Comment below line

* ls_input-DATETIME_NONUTC = <ls_input>-is_input-DATETIME_NONUTC.

. .

* From the SharePoint, we get the input(ls_input-date_of_birth) as * 1990-11-12T00:00:00, this needs to modified to 19901112

ls_input-date_of_birth

= ziwtng_cl_datetime_util=>get_date_in( <ls_input>-is_input-date_of_birth ).

* From the SharePoint, we get the input(datetime_nonutc) as * 2012-03-04T05:06:00, this needs to modified to 20120304050600

ls_input-datetime_nonutc

= ziwtng_cl_datetime_util=>get_timestamp_in( <ls_input>-is_input-datetime_nonutc ).

* From the SharePoint, we get the input(time) as * YYYY-MM-DDTHH:MM:SS this needs to modified to HHMMSS

ls_input-time

= ziwtng_cl_datetime_util=>get_time_in( <ls_input>-is_input-time ).

* Invoking SOAP Bridge API for create CALL METHOD /iwfnd/cl_soap_bridge=>create

EXPORTING iv_request_uuid = ls_input-user_iwxcreate_request_s-request_id iv_consumer_type_code = /iwtng/if_common_const=>gcv_consumer_typ_code iv_cor_gsdo_type = /iwtng/cl_gl_constants=>gc_gsdo_user iv_exception_class_name = /iwtng/cl_gl_constants=>gc_exception_class is_input = ls_input-user_iwxcreate_request_s-item IMPORTING es_output = output-attachment_iwxcreate_response-user_id.

(19)

Custom form for handling Date Types

We would consider an ECT that would show the following: 1. Non UTC Date (Date Of Birth)

2. Non UTC Date & Time 3. UTC Date & Time 4. Time

By following the previous steps as mentioned we would be able to receive the models but this data type inside it would still have date time type. So we need to change them to string format.

We can do this by simply replacing: 1.

By

2.

By

Also, as these type descriptors were previously of type DateTime we get few additional fields which need to be removed.

So from the model, remove all the occurrences of:

And

Once this step is done we would update the model with the correct endpoint and upload it in the central admin.

(20)

Before we proceed forward, it is advisable that you familiarize yourself with custom forms and how to build them.

Now we have to build a custom UI to show case the data. Building a Display form would be straight forward as there are no new controls required here. For edit(Update Scenario) and new forms(Create Scenario) we will introduce two DateTimePickerControl. One for Date_Of_Birth and the other for DATETIME_NONUTC. While adding the picker for the Date_Of_Birth scenario, we need to make sure that the DateOnly property for the DateTimePickerControl is set to true. This is done so that the time drop downs are not shown in the UI.

So, the below markup would show the custom control that we are building up for UPDATE scenario.

<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/datepicker.css"/> <asp:Table ID="Table1" runat="server" Width="100%">

<asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel2" FieldName="USER_NAME" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldUSER_NAME" ControlMode="Edit" FieldName="USER_NAME" />

</asp:TableCell> </asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel1" FieldName="DATE_OF_BIRTH" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldDATE_OF_BIRTH" ControlMode="Display" FieldName="DATE_OF_BIRTH" Visible="false"/>

<SharePoint:DateTimeControl runat="server" ID="DATE_OF_BIRTH_PICKER" DateOnly="True"/>

</asp:TableCell> </asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel3" FieldName="DATETIME_NONUTC" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldDATETIME_NONUTC" ControlMode="Display" FieldName="DATETIME_NONUTC" Visible="false"/>

<SharePoint:DateTimeControl runat="server" ID="DATETIME_NONUTC_PICKER" /> </asp:TableCell>

</asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel4" FieldName="DATETIME_UTC" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldDATETIME_UTC" ControlMode="Edit" FieldName="DATETIME_UTC" />

(21)

</asp:TableCell>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel5" FieldName="TIME" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldTIME" ControlMode="Display" FieldName="TIME" Visible="false"/>

<SharePoint:DateTimeControl runat="server" ID="TimeOFBirth" TimeOnly="true"/>

</asp:TableCell>

</asp:TableRow>

<asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel5" FieldName="ID" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldID" ControlMode="Display" FieldName="ID" />

</asp:TableCell> </asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel6" FieldName="ESDATRID" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldESDATRID" ControlMode="Edit" FieldName="ESDATRID" />

</asp:TableCell> </asp:TableRow>

</asp:Table>

Pay notice that DATE_OF_BIRTH_PICKER control has DateOnly property set to true & TimeOFBirth picker control has TimeOnly property set to true.

Next we go on building the New items form (CREATE Scenario) as shown below:

<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/datepicker.css"/> <asp:Table ID="Table1" runat="server" Width="100%">

<asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel2" FieldName="USER_NAME" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldUSER_NAME" ControlMode="New" FieldName="USER_NAME" />

(22)

</asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel1" FieldName="DATE_OF_BIRTH" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:DateTimeControl runat="server" ID="DATE_OF_BIRTH_PICKER" DateOnly="True"/>

</asp:TableCell> </asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel3" FieldName="DATETIME_NONUTC" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:DateTimeControl runat="server" ID="DATETIME_NONUTC_PICKER" /> </asp:TableCell>

</asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel4" FieldName="DATETIME_UTC" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldDATETIME_UTC" ControlMode="New" FieldName="DATETIME_UTC" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel5" FieldName="TIME" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldTIME" ControlMode="Display" FieldName="TIME" Visible="false"/>

<SharePoint:DateTimeControl runat="server" ID="TimeOFBirth" TimeOnly="true"/>

</asp:TableCell>

</asp:TableRow> <asp:TableRow>

<asp:TableCell CssClass="ms-formlabel">

<SharePoint:FieldLabel runat="server" ID="FieldLabel5" FieldName="ID" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldID" ControlMode="Display" FieldName="ID" />

</asp:TableCell> </asp:TableRow> <asp:TableRow>

(23)

<SharePoint:FieldLabel runat="server" ID="FieldLabel6" FieldName="ESDATRID" DisplaySize="5" />

</asp:TableCell>

<asp:TableCell CssClass="ms-formbody">

<SharePoint:FormField runat="server" ID="ffldESDATRID" ControlMode="New" FieldName="ESDATRID" />

</asp:TableCell> </asp:TableRow> </asp:Table>

With the above markup, our new forms are ready. Next our work would be to capture the data filled by the user in these controls and populate our backend parameter (string parameter) with it in the format that is mutually agreed by the SharePoint and ABAP developer. In our case the format had been decided as „yyyy-MM-ddTHH:mm:ss‟.

These data need to be captured during the save event of the form , so we will go ahead and override the out of the box save handler and place our own save handler in there using the following piece of code.

Next, would be to defince our save handler wherein we would take the data from the controls and populate the backend parameters. This can be done by the following piece of code.

In case of edit form, we also need to make sure that the data received from the string parameters are properly rendered onto the screen using the DateTimePickerControl. For this we need to override the Pre-render event of our edit page so that we can populate the controls before they are Pre-rendered onto the screen. We can override the Pre_render event in the constructor of our Edit Page web part using the code shown blow.

Once we have overridden the event, let‟s use our own event handler to populate the data. The code block that will help us do that is listed below.

protected void Page_Load(object sender, EventArgs e) {

SPContext.Current.FormContext.OnSaveHandler += FormSaveHandler; }

private void FormSaveHandler(object sender, EventArgs args) {

//Before the mapping is done, please decide upon a date format with the ABAP developer

SPContext.Current.Item["DATE_OF_BIRTH"] = DATE_OF_BIRTH_PICKER.SelectedDate.ToString("yyyy-MM-ddTHH:mm:ss"); SPContext.Current.Item["DATETIME_NONUTC"] = DATETIME_NONUTC_PICKER.SelectedDate.ToString("yyyy-MM-ddTHH:mm:ss"); SPContext.Current.Item["TIME"] = TimeOFBirth.SelectedDate.ToString("yyyy-MM-ddTHH:mm:ss");

SaveButton.SaveItem(SPContext.Current, false, String.Empty); }

protected EditFormUserControl() {

this.PreRender += Page_PreRender; }

(24)

protected void Page_PreRender(object sender, EventArgs args) {

if (!IsPostBack) {

MakeDateSelections();

private void MakeDateSelections() {

/* We are doing the following checks

*1. If the data from the backend is not null (data returned as object here)

*2. If the control is not uninitialized

*3. The object type data returned by the backend has a non emptyString value

*4. It is not equivalent to the current selection of DateTimeControlPicker */

if (ffldDATETIME_NONUTC != null && ffldDATETIME_NONUTC.ItemFieldValue != null && !String.IsNullOrEmpty(ffldDATETIME_NONUTC.ItemFieldValue.ToString()) && ffldDATETIME_NONUTC.ItemFieldValue.ToString() != DATETIME_NONUTC_PICKER.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldDATETIME_NONUTC.ItemFieldValue.ToString()); DATETIME_NONUTC_PICKER.SelectedDate = dateTime; }

// Same validation as mentioned above is also done for Date Of Birth field. if (ffldDATE_OF_BIRTH != null && ffldDATE_OF_BIRTH.ItemFieldValue != null && !String.IsNullOrEmpty(ffldDATE_OF_BIRTH.ItemFieldValue.ToString()) && ffldDATE_OF_BIRTH.ItemFieldValue.ToString() != DATE_OF_BIRTH_PICKER.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldDATE_OF_BIRTH.ItemFieldValue.ToString()); DATE_OF_BIRTH_PICKER.SelectedDate = dateTime; }

if (ffldTIME != null && ffldTIME.ItemFieldValue != null

&& !String.IsNullOrEmpty(ffldTIME.ItemFieldValue.ToString()) && ffldTIME.ItemFieldValue.ToString() != TimeOFBirth.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldTIME.ItemFieldValue.ToString()); TimeOFBirth.SelectedDate = dateTime; }

protected void Page_PreRender(object sender, EventArgs args) {

if (!IsPostBack) {

MakeDateSelections();

(25)

{

/* We are doing the following checks

*1. If the data from the backend is not null (data returned as object here)

*2. If the control is not uninitialized

*3. The object type data returned by the backend has a non emptyString value

*4. It is not equivalent to the current selection of DateTimeControlPicker */

if (ffldDATETIME_NONUTC != null && ffldDATETIME_NONUTC.ItemFieldValue != null && !String.IsNullOrEmpty(ffldDATETIME_NONUTC.ItemFieldValue.ToString()) && ffldDATETIME_NONUTC.ItemFieldValue.ToString() != DATETIME_NONUTC_PICKER.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldDATETIME_NONUTC.ItemFieldValue.ToString()); DATETIME_NONUTC_PICKER.SelectedDate = dateTime; }

// Same validation as mentioned above is also done for Date Of Birth field. if (ffldDATE_OF_BIRTH != null && ffldDATE_OF_BIRTH.ItemFieldValue != null && !String.IsNullOrEmpty(ffldDATE_OF_BIRTH.ItemFieldValue.ToString()) && ffldDATE_OF_BIRTH.ItemFieldValue.ToString() != DATE_OF_BIRTH_PICKER.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldDATE_OF_BIRTH.ItemFieldValue.ToString()); DATE_OF_BIRTH_PICKER.SelectedDate = dateTime; }

if (ffldTIME != null && ffldTIME.ItemFieldValue != null

&& !String.IsNullOrEmpty(ffldTIME.ItemFieldValue.ToString()) && ffldTIME.ItemFieldValue.ToString() != TimeOFBirth.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldTIME.ItemFieldValue.ToString()); TimeOFBirth.SelectedDate = dateTime; }

protected void Page_PreRender(object sender, EventArgs args) {

if (!IsPostBack) {

MakeDateSelections(); }

private void MakeDateSelections() {

/* We are doing the following checks

*1. If the data from the backend is not null (data returned as object here)

*2. If the control is not uninitialized

(26)

*4. It is not equivalent to the current selection of DateTimeControlPicker */

if (ffldDATETIME_NONUTC != null && ffldDATETIME_NONUTC.ItemFieldValue != null && !String.IsNullOrEmpty(ffldDATETIME_NONUTC.ItemFieldValue.ToString()) && ffldDATETIME_NONUTC.ItemFieldValue.ToString() != DATETIME_NONUTC_PICKER.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldDATETIME_NONUTC.ItemFieldValue.ToString()); DATETIME_NONUTC_PICKER.SelectedDate = dateTime; }

// Same validation as mentioned above is also done for Date Of Birth field. if (ffldDATE_OF_BIRTH != null && ffldDATE_OF_BIRTH.ItemFieldValue != null && !String.IsNullOrEmpty(ffldDATE_OF_BIRTH.ItemFieldValue.ToString()) && ffldDATE_OF_BIRTH.ItemFieldValue.ToString() != DATE_OF_BIRTH_PICKER.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldDATE_OF_BIRTH.ItemFieldValue.ToString()); DATE_OF_BIRTH_PICKER.SelectedDate = dateTime; }

if (ffldTIME != null && ffldTIME.ItemFieldValue != null

&& !String.IsNullOrEmpty(ffldTIME.ItemFieldValue.ToString()) && ffldTIME.ItemFieldValue.ToString() != TimeOFBirth.SelectedDate.ToString()) { DateTime dateTime = DateTime.Parse(ffldTIME.ItemFieldValue.ToString()); TimeOFBirth.SelectedDate = dateTime;

With these changes datetime custom form is ready to be deployed. Once everything is up and running, our final screen would look like:

(27)

Copyright

© Copyright 2012 SAP AG. All rights reserved.

No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP AG. The information contained herein may be changed without prior notice.

Some software products marketed by SAP AG and its distributors contain proprietary software components of other software vendors.

Microsoft, Windows, Excel, Outlook, and PowerPoint are registered trademarks of Microsoft Corporation.

IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, System z9, z10, z9, iSeries, pSeries, xSeries, zSeries, eServer, z/VM, z/OS, i5/OS, S/390, OS/390, OS/400, AS/400, S/390 Parallel Enterprise Server, PowerVM, Power Architecture, POWER6+, POWER6, POWER5+, POWER5, POWER, OpenPower, PowerPC, BatchPipes, BladeCenter, System Storage, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, Parallel Sysplex, MVS/ESA, AIX, Intelligent Miner, WebSphere, Netfinity, Tivoli and Informix are trademarks or registered trademarks of IBM Corporation.

Linux is the registered trademark of Linus Torvalds in the U.S. and other countries.

Adobe, the Adobe logo, Acrobat, PostScript, and Reader are either trademarks or registered trademarks of Adobe Systems Incorporated in the United States and/or other countries.

Oracle is a registered trademark of Oracle Corporation.

UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.

Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of Citrix Systems, Inc.

HTML, XML, XHTML and W3C are trademarks or registered trademarks of W3C®, World Wide Web Consortium, Massachusetts Institute of Technology.

Java is a registered trademark of Oracle Corporation.

JavaScript is a registered trademark of Oracle Corporation, used under license for technology invented and implemented by Netscape.

SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP Business ByDesign, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other countries.

Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Business Objects S.A. in the United States and in other countries. Business Objects is an SAP company.

All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document serves informational purposes only. National product specifications may vary.

These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional warranty.

References

Related documents

In reflection of this, the present research examined the relative importance of menopausal status, VMS, psychological health (depression and anxiety) and health

Crude protein, crude lipid and ash of fish carcass were not significantly different between dietary treatments with the exception of crude lipid of fish fed with Diet

What was the average (arithmetic mean) cost of all the adults' and children's tickets sold at the theater yesterday.. (1) Yesterday the ratio o f the number of children's tickets

Research Award, National Science Council in Taiwan, 1997, “A study of career barriers perceived by college students in Taiwan”. Research Award, National Science Council in

Any decision made after a Strategy Discussion that further child protection action by Children’s Social Care Services and/or the Police is not necessary as there is insufficient

As the analysis will show, the answer turns out to depend on the specific measure of absorptive capacity we look at, and which particular Arab country we are evaluating, but

In this paper we argue that the preferential tax treatment of newspapers increases media diversity, but may lead to higher newspaper prices and lower investments in quality.. In

I would love to set up a time to discuss how we might fit Arbonne in and around your life.” Share a little about how Arbonne has changed your life/cons - what you have achieved