#region Namespace
using System;
using System.Diagnostics;
using System.Reflection;
using System.ServiceModel;
using com.itac.mes.proxy;
using www.siplace.com.OIB._2008._05.SetupCenter.Contracts.Data;
using www.siplace.com.OIB._2008._05.SetupCenter.Contracts.Service;
using OibClient = Asm.As.Oib.Client;
using com.itac.mes.imsapi.domain.container;
using System.Collections.Generic;
using com.itac.mes.imsapi;
using KeyValue = com.itac.mes.imsapi.domain.container.KeyValue;
using com.itac.mes.imsapi.data;
using System.Configuration;
using com.itac.mes.simm;
using com.itac.mes.tools;
using com.itac.mes.imsapi.client.dotnet;
#endregion
namespace Itac.Oib.Simm
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SetupCenterExternalControlReceiver : ISiplaceSetupCenterExternalControl, IDisposable, IReceiver
{
#region Fields
private readonly OibClient.OibSetupCenterExternalControlEvents _oibSetupCenterExternalControlEvents;
private IIMSApiDotNet imsapi;
private IMSApiSessionContextStruct sessionContext;
private ItacXmlSerializer serializer;
private long firstASMTime = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
private long msdOpenTime = DateTime.MinValue.Ticks;
private long lastItacTimeTicks = new DateTime(3000, 12, 31, 23, 59, 59, DateTimeKind.Utc).Ticks;
private long firstItacTimeTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
///
/// the station Number is configured, must not be empty and MUST exist and valid!!!
/// if the stationNumber is not valid (licensed etc) all requests are rejected!!
///
private string stationNumber;
private int transactionCode;
// some optional values, default false
private bool mslLevelCheck;
private ConfigCode expirationMaster;
private ConfigCode mslMaster;
private ConfigCode quantityMaster;
#endregion
#region Constructor
public SetupCenterExternalControlReceiver(OibClient.OibSetupCenterExternalControlEvents oibSetupCenterExternalControlEvents, IIMSApiDotNet imsapi, IMSApiSessionContextStruct newSessionContext,
String stationNumber, int transactionCode,
ConfigCode quantityMaster, ConfigCode mslMaster, ConfigCode expirationMaster)
{
_oibSetupCenterExternalControlEvents = oibSetupCenterExternalControlEvents;
if (oibSetupCenterExternalControlEvents != null)
{
oibSetupCenterExternalControlEvents.Ping = Ping;
oibSetupCenterExternalControlEvents.GetNewPackagingUnitData = GetNewPackagingUnitData;
oibSetupCenterExternalControlEvents.GetPackagingUnitControlStatus = GetPackagingUnitControlStatus;
}
this.imsapi = imsapi;
this.sessionContext = newSessionContext;
this.stationNumber = stationNumber;
this.transactionCode = transactionCode;
this.quantityMaster = quantityMaster;
this.mslMaster = mslMaster;
this.expirationMaster = expirationMaster;
serializer = new ItacXmlSerializer();
// evaluate some optional parameters from appConfig file
if (!String.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings["mslLevelCheck"]))
{
mslLevelCheck = bool.Parse(ConfigurationManager.AppSettings["mslLevelCheck"].ToString());
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "optional parameter 'mslLevelCheck' set '" + mslLevelCheck.ToString() + "'");
}
}
public void Dispose()
{
if (_oibSetupCenterExternalControlEvents != null)
_oibSetupCenterExternalControlEvents.Dispose();
}
#endregion
#region Start/Stop
public void StartReceiver()
{
_oibSetupCenterExternalControlEvents.Start();
}
public void StopReceiver()
{
_oibSetupCenterExternalControlEvents.Stop();
}
#endregion
#region toolFunctions
// muss noch weiter getestet werden...
public void DeepCopy(object sourceObject, object destObject)
{
Type sourceType = sourceObject.GetType();
Type destType = destObject.GetType();
MemberInfo[] sourceMbrInfoArray = sourceType.GetMembers();
MemberInfo[] destMbrInfoArray = destType.GetMembers();
foreach (MemberInfo sourceMbrInfo in sourceMbrInfoArray)
{
if (sourceMbrInfo.MemberType == MemberTypes.Property)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Error, "" + sourceMbrInfo + " is a " + sourceMbrInfo.MemberType);
// alle einfachen TypeNameConverter direkt prüfen (int, String, bool)
// komplexe Typen ???
PropertyInfo sourcePropInfo = sourceType.GetProperty(sourceMbrInfo.Name);
// gibt es das Property auch im Zielobjekt
foreach (MemberInfo destMbrInfo in destMbrInfoArray)
{
// identischer Name, identischerr Typ
if (destMbrInfo.MemberType == sourceMbrInfo.MemberType && destMbrInfo.Name == sourceMbrInfo.Name)
{
PropertyInfo destPropInfo = destType.GetProperty(destMbrInfo.Name);
object sourceValue = sourcePropInfo.GetValue(sourceObject, null);
object destValue = destPropInfo.GetValue(destObject, null);
if (sourcePropInfo.PropertyType == typeof(String) || sourcePropInfo.PropertyType == typeof(int)
|| sourcePropInfo.PropertyType == typeof(Int32) || sourcePropInfo.PropertyType == typeof(Int64)
|| sourcePropInfo.PropertyType == typeof(long) || sourcePropInfo.PropertyType == typeof(bool)
|| sourcePropInfo.PropertyType == typeof(Boolean))
{
if (sourceValue != destValue)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "primitive type copy value");
destPropInfo.SetValue(destObject, sourceValue, null);
}
}
else if (!sourceType.IsArray)
{
// komplexer Typ, kein Array
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, sourceMbrInfo.Name + " is complex type ");
if (sourceValue != null)
{
DeepCopy(sourceValue, destValue);
}
else
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, sourceMbrInfo.Name + " is complex type, sourceValue is null");
}
}
}
}
}
}
}
public void applyToPackagingUnit(SmtContainer container, ref PackagingUnit p)
{
p.BatchId = container.supplierChargeNumber;
// p.BatchPackagingUnit=
p.BrightnessClass = container.classification; ;
// p.Comment="";
p.ComponentBarcode = "";
p.ComponentName = container.materialBinPartNumber;
// p.ConsumptionDate = getDateValue(resultValues[indexMap[""]]);
// special case: itac 31.12.3000 is unexpired, in ASM 31.12.9999
if (container.expirationDate >= new DateTime(2037, 12, 31))
{
p.ExpiryDate = DateTime.MaxValue.ToUniversalTime();
}
else
{
p.ExpiryDate = container.expirationDate; // getDateValue(resultValues[indexMap["EXPIRATION_DATE"]]);
}
// p.Extra1="";
// p.Extra2="";
// p.Extra3="";
// p.GreyZone=
if (p.LastProductionDate <= new DateTime(1901, 01, 01, 00, 00, 00, DateTimeKind.Utc))
{
p.LastProductionDate = DateTime.MinValue.ToUniversalTime();
}
// p.ManufactureLocation
// p.ManufacturePartNumber
p.Manufacturer = container.supplierName;
p.ManufacturerDate = container.dateCreated;
p.MsdLevel = MslLevel.toCode(container.mslLevel);
string mslState = container.mslState;
if ("C".Equals(mslState))
{
p.MsdOpenDate = DateTime.MinValue.ToUniversalTime();
}
else
{
// take open date from MES
p.MsdOpenDate = container.mslOpenDate;
// correction of MSD open Date when unopened
if (p.MsdOpenDate <= new DateTime(1901, 01, 01, 00, 00, 00, DateTimeKind.Utc))
{
p.MsdOpenDate = DateTime.MinValue.ToUniversalTime();
}
}
// p.OrderingCode = ;
p.OriginalQuantity = container.quantity;// Convert.ToInt32(double.Parse(resultValues[indexMap["MATERIAL_BIN_QTY_TOTAL"]]));
p.PurchaseOrderNumber = container.huNumber;
p.Quantity = container.materialBinQuantityActual; // Convert.ToInt32(Double.Parse(resultValues[indexMap["MATERIAL_BIN_QTY_ACTUAL"]]));
// p.RevisionLevel;
// p.RoHS
// p.Serial
// p.ShippingNoteNumber
// p.SplicedPackagingUnit
p.Supplier = container.supplierName;
// p.SupplierData
// p.UID;
}
public void mapValues(PackagingUnit pu, string[] materialBinUploadKeys, ref string[] result, int index)
{
foreach (string s in materialBinUploadKeys)
{
switch (s)
{
case "ERROR_CODE": result[index++] = "0"; break;
case "MATERIAL_BIN_NUMBER": result[index++] = pu.UID; break;
default: result[index++] = "0"; break;
}
}
}
public void deepAddUnit(PackagingUnit packUnit, ref Dictionary packagingUnitMap)
{
packagingUnitMap.Add(packUnit.UID, packUnit);
if (packUnit.SplicedPackagingUnit != null)
{
deepAddUnit(packUnit.SplicedPackagingUnit, ref packagingUnitMap);
}
}
#endregion toolFunctions
#region ISiplaceSetupCenterExternalControl Members
///
/// Check for the client if this service is available.
///
///
public bool Ping()
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "SetupCenterExternalControl.Ping");
return true;
}
///
/// Gets the packaging unit control status.
///
/// The packaging unit locations.
/// List of ExternalControlResults for reading the data
/// ResultState UNKNOWN=0;OK = 1;NOT_OK=2;
public ExternalControlResult[] GetNewPackagingUnitData(PackagingUnitLocation[] packagingUnitLocations)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "SetupCenterExternalControl.GetNewPackagingUnit()\n"
+ serializer.serialize(packagingUnitLocations).ToString());
KeyValue[] matBinfilters = new KeyValue[] { new KeyValue("MATERIAL_BIN_NUMBER", "") };
AttributeInfo[] attributes = new AttributeInfo[0];
string[] resultValues;
try
{
ExternalControlResult[] result = new ExternalControlResult[packagingUnitLocations.Length];
for (int i = 0; i < packagingUnitLocations.Length; i++)
{
result[i] = new ExternalControlResult();
result[i].PackagingUnit = packagingUnitLocations[i].PackagingUnit;
matBinfilters[0].value = packagingUnitLocations[i].PackagingUnit.UID;
int imsapiResult = imsapi.mlGetMaterialBinData(sessionContext, stationNumber, matBinfilters, attributes, SmtContainer.MAXIMAL_INFORMATION, out resultValues);
// return all relevant PackagingUnit infos known in iTAC.MES.Suite
if (imsapiResult < 0 || imsapiResult == 1) // 1 = no data found
{
result[i].ResultState = 2;
result[i].Messages = new ExternalControlResultMessage[] { new ExternalControlResultMessage() };
result[i].Messages[0].Message = "UID " + packagingUnitLocations[i].PackagingUnit.UID + " unknown in iTAC.MES.Suite";
}
else
{
// OK, Info gathered
result[i].ResultState = 1;
result[i].Messages = new ExternalControlResultMessage[] { };
PackagingUnit p = result[i].PackagingUnit;
try
{
SmtContainer knownContainer = new ImsApiMapTool().getStruct(typeof(SmtContainer), SmtContainer.MAXIMAL_INFORMATION, resultValues);
applyToPackagingUnit(knownContainer, ref p);
}
catch (Exception e)
{
result[i].ResultState = 2;
result[i].Messages = new ExternalControlResultMessage[] { new ExternalControlResultMessage() };
result[i].Messages[0].Message = e.Message.ToString();
}
}
}
LogHandler.log(Constants.LOGGER, TraceEventType.Information, serializer.serialize(result).ToString());
return result;
}
catch (Exception)
{
// Fehler, keine weitere info vorhanden, da die Applikation nicht läuft
return new ExternalControlResult[0];
}
}
///
/// Gets the packaging unit control status.
///
/// The packaging unit locations.
/// List of ExternalControlResults for reading the data
public ExternalControlResult[] GetPackagingUnitControlStatus(PackagingUnitLocation[] packagingUnitLocations)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "SetupCenterExternalControl.GetPackagingUnitControlStatus:\n"
+ serializer.serialize(packagingUnitLocations).ToString());
if (!mslLevelCheck)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "mslLevel check switched off by confguration");
}
KeyValue[] matBinfilters = new KeyValue[] { new KeyValue("MATERIAL_BIN_NUMBER", "") };
AttributeInfo[] attributes = new AttributeInfo[0];
// flag wether to update any qty or not.
LinkedList updateQtyList = new LinkedList();
try
{
ExternalControlResult[] result = new ExternalControlResult[packagingUnitLocations.Length];
for (int resultIndex = 0; resultIndex < packagingUnitLocations.Length; resultIndex++)
{
result[resultIndex] = new ExternalControlResult();
result[resultIndex].PackagingUnit = packagingUnitLocations[resultIndex].PackagingUnit;
PackagingUnit packagingUnit = packagingUnitLocations[resultIndex].PackagingUnit;
// ResultState UNKNOWN = 0; OK = 1; NOT_OK = 2;
result[resultIndex].ResultState = 1;
result[resultIndex].Messages = new ExternalControlResultMessage[] { };
string[] resultValues;
matBinfilters[0].value = packagingUnitLocations[resultIndex].PackagingUnit.UID;
int imsapiResult = imsapi.mlGetMaterialBinData(sessionContext, stationNumber, matBinfilters, attributes, SmtContainer.MINIMAL_INFORMATION, out resultValues);
if (imsapiResult < 0 || imsapiResult == 1) // 1 = no data found
{
// Packaging Units unknown in MES.Suite must be rejected
// Error, Packaging Unit not found in mes.suite
result[resultIndex].ResultState = 2;
ExternalControlResultMessage message = new ExternalControlResultMessage();
message.Message = "PackagingUnit '" + packagingUnitLocations[resultIndex].PackagingUnit.UID + "' unknown in iTAC.MES.Suite";
result[resultIndex].Messages = new ExternalControlResultMessage[] { message };
}
else
{
// find any differences in quantities and update the values in MES.Suite
SmtContainer knownContainer = new ImsApiMapTool().getStruct(typeof(SmtContainer), SmtContainer.MINIMAL_INFORMATION, resultValues);
LogHandler.log(Constants.LOGGER, TraceEventType.Information, serializer.serialize(knownContainer).ToString());
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "quantityMaster=" + quantityMaster);
adjustQuantity(quantityMaster, ref knownContainer, ref packagingUnit, ref updateQtyList);
// any differences in mslLevel?
if (mslLevelCheck)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "mslLevelCheck=true");
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, String.Format("UID: {0} MsdLevel(ASM): {1}, MslLevel(iTAC): {2}", packagingUnit.UID, packagingUnit.MsdLevel, knownContainer.mslLevel));
if (!knownContainer.mslLevel.ToLower().Equals(MslLevel.toString(packagingUnit.MsdLevel)))
{
// failure, wrong MslLevel
result[resultIndex].ResultState = 2;
ExternalControlResultMessage message = new ExternalControlResultMessage();
message.Message = String.Format("PackagingUnit {0} has MsdLevel {1} in SetupCenter, but Level {2} in iTAC.MES.Suite",
packagingUnit.UID, MslLevel.toString(packagingUnit.MsdLevel), knownContainer.mslLevel);
result[resultIndex].Messages = new ExternalControlResultMessage[] { message };
}
// continue with next container
continue;
}
// any differences in msl state?
if (mslMaster == ConfigCode.SIMM)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "mslMaster=" + mslMaster.ToString());
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, String.Format("UID: {0} MsdOpen(ASM): {1}, MslState(iTAC): {2}", packagingUnit.UID, isMsdOpen(packagingUnit.MsdOpenDate), knownContainer.mslState));
// iTAC states : C = geschützt / verschweißt(Closed) O = ungeschützt / offen(Open) B = in der Rücktrocknung (Baking)
// ASM closed: MsdOpenDate = 2.1.1900
KeyValue[] mslEventParams = new KeyValue[] { new KeyValue("BOOK_DATE", getImsApiDateString(packagingUnit.MsdOpenDate)) };
KeyValue[] mslStopEventParams = new KeyValue[] { new KeyValue("BOOK_DATE", "-1") };
string[] mslObjectKeys = new String[] { "ERROR_CODE", "MATERIAL_BIN_NUMBER" };
string[] mslObjectValues = new String[] { "0", packagingUnit.UID };
string[] mslResultValues = new String[] { };
if (knownContainer.mslState.Equals("C") && isMsdOpen(packagingUnit.MsdOpenDate))
{
// closed in iTAC, open in ASM--> required to open in iTAC!!!
int mslStartExpirationCode = imsapi.mslStartObjectExpiration(sessionContext, stationNumber, mslEventParams, mslObjectKeys, mslObjectValues, out mslResultValues);
if (mslStartExpirationCode < 0)
{
result[resultIndex].ResultState = 2;
ExternalControlResultMessage message = new ExternalControlResultMessage();
message.Message = String.Format("PackagingUnit {0} not opened in iTAC.MES.Suite", packagingUnit.UID);
result[resultIndex].Messages = new ExternalControlResultMessage[] { message };
continue;
}
}
else if (knownContainer.mslState.Equals("O") && !isMsdOpen(packagingUnit.MsdOpenDate) && packagingUnit.MsdOpenDate.Ticks > DateTime.MinValue.Ticks)
{
// open in iTAC, closed in ASM--> required to close in iTAC!!!
int mslStopExpirationCode = imsapi.mslStopObjectExpiration(sessionContext, stationNumber, mslStopEventParams, mslObjectKeys, mslObjectValues, out mslResultValues);
if (mslStopExpirationCode < 0)
{
result[resultIndex].ResultState = 2;
ExternalControlResultMessage message = new ExternalControlResultMessage();
message.Message = String.Format("PackagingUnit {0} not closed in iTAC.MES.Suite", packagingUnit.UID);
result[resultIndex].Messages = new ExternalControlResultMessage[] { message };
continue;
}
}
}
else if (mslMaster == ConfigCode.MES)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Warning, "this mode is currently not supported!");
}
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "expirationMaster=" + expirationMaster.ToString());
if (!adjustExpiration(expirationMaster, ref knownContainer, ref packagingUnit, ref imsapi, ref result[resultIndex]))
{
continue;
}
// SiMM-Corrections
if (packagingUnit.MsdOpenDate <= new DateTime(1900, 01, 01)) { packagingUnit.MsdOpenDate = DateTime.MinValue.ToUniversalTime(); }
if (packagingUnit.ConsumptionDate <= new DateTime(1900, 01, 01)) { packagingUnit.ConsumptionDate = DateTime.MinValue.ToUniversalTime(); }
if (packagingUnit.ExpiryDate <= new DateTime(1900, 01, 01)) { packagingUnit.ExpiryDate = DateTime.MinValue.ToUniversalTime(); }
if (packagingUnit.LastProductionDate <= new DateTime(1900, 01, 01)) { packagingUnit.LastProductionDate = DateTime.MinValue.ToUniversalTime(); }
if (packagingUnit.ManufacturerDate <= new DateTime(1900, 01, 01)) { packagingUnit.ManufacturerDate = DateTime.MinValue.ToUniversalTime(); }
}
}
if (quantityMaster == ConfigCode.SIMM && updateQtyList.Count > 0)
{
MaterialBinBooking[] matBinBookingArray = new MaterialBinBooking[updateQtyList.Count];
updateQtyList.CopyTo(matBinBookingArray, 0);
string[] materialBinBookingUploadValues = new ImsApiMapTool().getValueArray(matBinBookingArray, MaterialBinBooking.MAXIMAL_INFORMATION); ;
string[] materialBinBookingsResultValues = null;
int retUpdateQty = imsapi.mlUploadMaterialBinBooking(sessionContext, stationNumber, MaterialBinBooking.MAXIMAL_INFORMATION, materialBinBookingUploadValues, out materialBinBookingsResultValues);
}
LogHandler.log(Constants.LOGGER, TraceEventType.Information, serializer.serialize(result).ToString());
return result;
}
catch (Exception)
{
// Fehler, keine weitere info vorhanden, da die Applikation nicht läuft
return new ExternalControlResult[0];
}
}
public void adjustQuantity(ConfigCode quantityMaster, ref SmtContainer knownContainer, ref PackagingUnit packagingUnit, ref LinkedList updateQtyList)
{
if (quantityMaster == ConfigCode.SIMM)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, String.Format("UID: {0} Qty(ASM): {1}, Qty(iTAC): {2}", packagingUnit.UID, packagingUnit.Quantity, knownContainer.materialBinQuantityActual));
if (packagingUnit.Quantity != knownContainer.materialBinQuantityActual)
{
// udpate the MES with the quantity from ASM
MaterialBinBooking matBinBooking = new MaterialBinBooking();
matBinBooking.materialBinNumber = packagingUnit.UID;
matBinBooking.transactionCode = transactionCode.ToString();
matBinBooking.materialBinQuantityActual = packagingUnit.Quantity;
updateQtyList.AddLast(matBinBooking);
}
}
else if (quantityMaster == ConfigCode.MES)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, String.Format("UID: {0} Qty(ASM): {1}, Qty(iTAC): {2}", packagingUnit.UID, packagingUnit.Quantity, knownContainer.materialBinQuantityActual));
if (packagingUnit.Quantity != knownContainer.materialBinQuantityActual)
{
packagingUnit.Quantity = knownContainer.materialBinQuantityActual;
}
}
}
public bool adjustExpiration(ConfigCode expirationMaster, ref SmtContainer knownContainer, ref PackagingUnit packagingUnit, ref IIMSApiDotNet imsapi, ref ExternalControlResult result)
{
if (expirationMaster == ConfigCode.SIMM)
{
if (packagingUnit.ExpiryDate == DateTime.MinValue)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, String.Format("UID: {0} no expiration set", packagingUnit.UID));
return true;
}
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, String.Format("UID: {0} expiryDate(ASM): {1}, expirationDate(iTAC): {2}", packagingUnit.UID, packagingUnit.ExpiryDate, knownContainer.expirationDate));
if (expirationDateDifferent(packagingUnit.ExpiryDate, knownContainer.expirationDate))
{
// update expirationDate in iTAC
KeyValue[] keyValueArray = new KeyValue[1];
keyValueArray[0] = new KeyValue("EXPIRATION_DATE_FINAL", getImsApiDateString(packagingUnit.ExpiryDate));
int changeBinResult = imsapi.mlChangeMaterialBinData(sessionContext, stationNumber, packagingUnit.UID, keyValueArray);
if (changeBinResult < 0)
{
// reject container
result.ResultState = 2;
ExternalControlResultMessage message = new ExternalControlResultMessage();
message.Message = String.Format("PackagingUnit {0} expiration date final not updated in iTAC.MES.Suite", packagingUnit.UID);
result.Messages = new ExternalControlResultMessage[] { message };
return false;
}
}
}
else if (expirationMaster == ConfigCode.MES)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Warning, "this mode is currently not supported!");
return true;
}
return true;
}
public string getImsApiDateString(DateTime expiryDate)
{
if (expiryDate.Ticks >= lastItacTimeTicks)
{
return "32535212399000";
}
if (expiryDate.Ticks <= firstItacTimeTicks)
{
return "0";
}
return expiryDate.ToUniversalTime().Subtract(
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
).TotalMilliseconds.ToString();
}
public bool expirationDateDifferent(DateTime expiryDate, DateTime expirationDate)
{
// both values after 30.12.3000 00:00:00 --> same...
if (expiryDate.Day >= 30 && expiryDate.Month >= 12 && expiryDate.Year >= 3000 &&
expirationDate.Day >= 30 && expirationDate.Month >= 12 && expirationDate.Year >= 3000) { return false; }
return expiryDate.Ticks != expirationDate.Ticks;
}
public bool isMsdOpen(DateTime msdOpenDate)
{
return (msdOpenDate.Ticks > msdOpenTime);
}
#endregion
}
}