// timer is milliseconds elapsed since 1/1/1601
struct tm * tinyclr_gmtime ( const time_t * timer )
{
    SYSTEMTIME systime;
    INT64 offset = Time_GetTimeZoneOffset() * 60; // convert to seconds

    INT64 tim = (INT64)(UINT32)(*timer);
    INT64 utctime = (tim + offset) * MF_TIME_TO_SECONDS + s_TimeUntil1900; // convert to seconds since 1900
    Time_ToSystemTime(utctime, &systime); 
    g_timestruct.tm_hour = systime.wHour;
    g_timestruct.tm_mday = systime.wDay;
    g_timestruct.tm_min = systime.wMinute;
    g_timestruct.tm_mon = systime.wMonth - 1; // SYSTEMTIME structure is one based and struct tm is zero based
    g_timestruct.tm_sec = systime.wSecond;
    g_timestruct.tm_wday = systime.wDayOfWeek;
    g_timestruct.tm_year = systime.wYear - 1900; // struct tm records years since 1900
    return &g_timestruct;
}
void Time_GetDateTime(DATE_TIME_INFO* dt)
{
    NATIVE_PROFILE_CLR_NETWORK();
    SYSTEMTIME st;

    CLR_INT64 lt = Time_GetLocalTime();    

    Time_ToSystemTime( lt, &st );

    dt->tzOffset = Time_GetTimeZoneOffset() * 60;

    dt->year   = st.wYear;
    dt->month  = st.wMonth;
    dt->day    = st.wDay;
    dt->hour   = st.wHour;
    dt->minute = st.wMinute;
    dt->second = st.wSecond;
    dt->msec   = st.wMilliseconds;

    dt->dlsTime  = 0;
 }
HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::ParseCertificate___STATIC__VOID__SZARRAY_U1__STRING__BYREF_STRING__BYREF_STRING__BYREF_mscorlibSystemDateTime__BYREF_mscorlibSystemDateTime( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* arrData    = stack.Arg0().DereferenceArray(); 
    CLR_UINT8*              certBytes;
    CLR_RT_HeapBlock        hbIssuer;
    CLR_RT_HeapBlock        hbSubject;
    CLR_RT_ProtectFromGC    gc1( hbIssuer  );
    CLR_RT_ProtectFromGC    gc2( hbSubject );
    X509CertData            cert;
    CLR_INT64*              val;
    CLR_INT64               tzOffset;
    SYSTEMTIME              st;
    INT32                   standardBias;
    CLR_RT_HeapBlock*       hbPwd     = stack.Arg1().DereferenceString();
    LPCSTR                  szPwd;


    FAULT_ON_NULL_ARG(hbPwd);

    szPwd = hbPwd->StringText();

    CLR_RT_Memory::ZeroFill( &cert, sizeof(cert) );

    FAULT_ON_NULL(arrData);

    certBytes = arrData->GetFirstElement();

    if(!SSL_ParseCertificate( (const char*)certBytes, arrData->m_numOfElements, szPwd, &cert )) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbIssuer, cert.Issuer ));
    TINYCLR_CHECK_HRESULT(hbIssuer.StoreToReference( stack.Arg2(), 0 ));

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbSubject, cert.Subject ));
    TINYCLR_CHECK_HRESULT(hbSubject.StoreToReference( stack.Arg3(), 0 ));

    st.wYear         = cert.EffectiveDate.year;
    st.wMonth        = cert.EffectiveDate.month;
    st.wDay          = cert.EffectiveDate.day;
    st.wHour         = cert.EffectiveDate.hour;
    st.wMinute       = cert.EffectiveDate.minute;
    st.wSecond       = cert.EffectiveDate.second;
    st.wMilliseconds = cert.EffectiveDate.msec;

    standardBias     = Time_GetTimeZoneOffset();
    standardBias    *= TIME_CONVERSION__ONEMINUTE;

    val = Library_corlib_native_System_DateTime::GetValuePtr( stack.Arg4() );
    *val = Time_FromSystemTime( &st );

    tzOffset = cert.EffectiveDate.tzOffset;

    // adjust for timezone differences
    if(standardBias != tzOffset)
    {
        *val += tzOffset - standardBias; 
    }

    st.wYear         = cert.ExpirationDate.year;
    st.wMonth        = cert.ExpirationDate.month;
    st.wDay          = cert.ExpirationDate.day;
    st.wHour         = cert.ExpirationDate.hour;
    st.wMinute       = cert.ExpirationDate.minute;
    st.wSecond       = cert.ExpirationDate.second;
    st.wMilliseconds = cert.ExpirationDate.msec;
    
    val = Library_corlib_native_System_DateTime::GetValuePtr( stack.ArgN( 5 ) );
    *val = Time_FromSystemTime( &st );

    tzOffset = cert.ExpirationDate.tzOffset;
    
    if(standardBias != tzOffset)
    {
       *val += tzOffset - standardBias; 
    }

    TINYCLR_NOCLEANUP();
}