goenning / SharpSapRfc

Making SAP RFC calls even easier with .NET
MIT License
84 stars 27 forks source link

Date and Time ABAP Types Conversion #10

Closed Slaski closed 10 years ago

Slaski commented 10 years ago

Hi again,

Something I've also noticed when I tried to get the information of the column ERDAT in the PRPS table (Creation Date) is that it doesn't convert to the DateTime type. The Date type is received from the SAP in the "YYYYMMDD" format, and the Time type is received in the "HHMMSS" format. So I've implemented the following solution that I leave here as a suggestion.

I've created the AbapDateTime class:

using SAP.Middleware.Connector;
using System;
using System.Threading;
using System.Globalization;

namespace SharpSapRfc
{
    public class AbapDateTime
    {
        public static DateTime FromString(string value)
        {
            DateTime date;

            if (DateTime.TryParse(value, out date))
            {
                return date;
            }
            else if (DateTime.TryParseExact(value, new string[] { "yyyyMMdd", "HHmmss" }, Thread.CurrentThread.CurrentCulture, DateTimeStyles.AssumeLocal, out date))
            {
                return date;
            }
            else if (value == "00000000" || value == "000000") // ABAP Date and Time initial value
            {
                return DateTime.MinValue;
            }
            else
            {
                string message = string.Format("{0} is not a valid Date format.", value);
                throw new RfcAbapException("UNKNOWN_DATETIME_FORMAT", message, message);
            }
        }

        public static string ToString(DateTime value, AbapDateTimeType type)
        {
            if (type == AbapDateTimeType.Date)
            {
                return value.ToString("yyyyMMdd");
            }
            else if (type == AbapDateTimeType.Time)
            {
                return value.ToString("HHmmss");
            }
            else
            {
                return value.ToString();
            }
        }
    }

    public enum AbapDateTimeType
    {
        Date,
        Time
    }
}

I've also changed the RfcStructureMapper.FromRfcReadTableToList to call this class for DateTime types:

PropertyInfo property = null;
if (typeProperties[type].TryGetValue(field.FieldName.ToLower(), out property))
{
    string value = null;
    if (field.Offset >= row.Data.Length)
        value = string.Empty;
    else if (field.Length + field.Offset > row.Data.Length)
        value = row.Data.Substring(field.Offset).TrimEnd();
    else
        value = row.Data.Substring(field.Offset, field.Length).TrimEnd();

    object targetValue = null;
    if (property.PropertyType.Equals(typeof(Boolean)))
        targetValue = AbapBool.FromString(value.ToString());
    else if (property.PropertyType.Equals(typeof(DateTime)))
        targetValue = AbapDateTime.FromString(value.ToString());
    else
        targetValue = Convert.ChangeType(value, property.PropertyType, System.Globalization.CultureInfo.CurrentCulture);
    property.SetValue(entry, targetValue, null);
}

And the RfcStructureMapper.CreateStructure:

PropertyInfo property = null;
if (typeProperties[type].TryGetValue(fieldName.ToLower(), out property))
{
    object value = property.GetValue(parameterObject, null);
    if (property.PropertyType.Equals(typeof(Boolean)))
    {
        value = AbapBool.ToString((Boolean)value);
    }
    else if (property.PropertyType.Equals(typeof(DateTime)))
    {
        if (metadata[i].DataType == RfcDataType.DATE)
        {
            value = AbapDateTime.ToString((DateTime)value, AbapDateTimeType.Date);
        }
        else if (metadata[i].DataType == RfcDataType.TIME)
        {
            value = AbapDateTime.ToString((DateTime)value, AbapDateTimeType.Time);
        }
    }
    structure.SetValue(fieldName, value);
}

And the RfcStructureMapper.FromStructure too:

PropertyInfo property = null;
if (typeProperties[type].TryGetValue(fieldName.ToLower(), out property))
{
    object value = structure.GetValue(fieldName);
    if (property.PropertyType.Equals(typeof(Boolean)))
        value = AbapBool.FromString(value.ToString());
    else if (property.PropertyType.Equals(typeof(Int32)))
        value = Convert.ToInt32(value);
    else if (property.PropertyType.Equals(typeof(DateTime)))
        value = AbapDateTime.FromString(value.ToString());

    property.SetValue(returnValue, value, null);
}

Regards,

Slaski

goenning commented 10 years ago

to be released in version 1.0.2