Port Constants, Globals, DateAndTime (dotnet/corefx#37376)
authorCharles Stoner <chucks@microsoft.com>
Fri, 3 May 2019 14:21:35 +0000 (07:21 -0700)
committerStephen Toub <stoub@microsoft.com>
Fri, 3 May 2019 14:21:35 +0000 (10:21 -0400)
* Port Constants, Globals, DateAndTime

* PR feedback

* Add DateString test

* Remove using

Commit migrated from https://github.com/dotnet/corefx/commit/ecb4d648de5edbfb9f6907cc05c5e98f7005460e

12 files changed:
src/libraries/Microsoft.VisualBasic.Core/ref/Microsoft.VisualBasic.Core.cs
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft.VisualBasic.Core.vbproj
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CallType.vb [deleted file]
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/Utils.LateBinder.vb
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/Utils.vb
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/Constants.vb
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/DateAndTime.vb
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/Globals.vb
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/Helpers/SafeNativeMethods.vb [new file with mode: 0644]
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/Helpers/UnsafeNativeMethods.vb
src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/VariantType.vb [deleted file]
src/libraries/Microsoft.VisualBasic.Core/tests/DateAndTimeTests.cs

index 3ceaf6a..2a92c08 100644 (file)
@@ -7,6 +7,15 @@
 
 namespace Microsoft.VisualBasic
 {
+    public enum AppWinStyle : short
+    {
+        Hide = 0,
+        MaximizedFocus = 3,
+        MinimizedFocus = 2,
+        MinimizedNoFocus = 6,
+        NormalFocus = 1,
+        NormalNoFocus = 4,
+    }
     public enum CallType
     {
         Method = 1,
@@ -65,44 +74,109 @@ namespace Microsoft.VisualBasic
     public sealed partial class Constants
     {
         internal Constants() { }
+        public const MsgBoxResult vbAbort = MsgBoxResult.Abort;
+        public const MsgBoxStyle vbAbortRetryIgnore = MsgBoxStyle.AbortRetryIgnore;
+        public const MsgBoxStyle vbApplicationModal = MsgBoxStyle.ApplicationModal;
         public const FileAttribute vbArchive = FileAttribute.Archive;
+        public const VariantType vbArray = VariantType.Array;
         public const string vbBack = "\b";
         public const Microsoft.VisualBasic.CompareMethod vbBinaryCompare = Microsoft.VisualBasic.CompareMethod.Binary;
+        public const VariantType vbBoolean = VariantType.Boolean;
+        public const VariantType vbByte = VariantType.Byte;
+        public const MsgBoxResult vbCancel = MsgBoxResult.Cancel;
         public const string vbCr = "\r";
+        public const MsgBoxStyle vbCritical = MsgBoxStyle.Critical;
         public const string vbCrLf = "\r\n";
+        public const VariantType vbCurrency = VariantType.Currency;
+        public const VariantType vbDate = VariantType.Date;
+        public const VariantType vbDecimal = VariantType.Decimal;
+        public const MsgBoxStyle vbDefaultButton1 = MsgBoxStyle.ApplicationModal;
+        public const MsgBoxStyle vbDefaultButton2 = MsgBoxStyle.DefaultButton2;
+        public const MsgBoxStyle vbDefaultButton3 = MsgBoxStyle.DefaultButton3;
         public const FileAttribute vbDirectory = FileAttribute.Directory;
+        public const VariantType vbDouble = VariantType.Double;
+        public const VariantType vbEmpty = VariantType.Empty;
+        public const MsgBoxStyle vbExclamation = MsgBoxStyle.Exclamation;
         public const TriState vbFalse = TriState.False;
+        public const FirstWeekOfYear vbFirstFourDays = FirstWeekOfYear.FirstFourDays;
+        public const FirstWeekOfYear vbFirstFullWeek = FirstWeekOfYear.FirstFullWeek;
+        public const FirstWeekOfYear vbFirstJan1 = FirstWeekOfYear.Jan1;
         public const string vbFormFeed = "\f";
+        public const FirstDayOfWeek vbFriday = FirstDayOfWeek.Friday;
         public const DateFormat vbGeneralDate = DateFormat.GeneralDate;
+        public const CallType vbGet = CallType.Get;
+        public const AppWinStyle vbHide = AppWinStyle.Hide;
         public const FileAttribute vbHidden = FileAttribute.Hidden;
         public const VbStrConv vbHiragana = VbStrConv.Hiragana;
+        public const MsgBoxStyle vbInformation = MsgBoxStyle.Information;
+        public const MsgBoxResult vbIgnore = MsgBoxResult.Ignore;
+        public const VariantType vbInteger = VariantType.Integer;
         public const VbStrConv vbKatakana = VbStrConv.Katakana;
+        public const CallType vbLet = CallType.Let;
         public const string vbLf = "\n";
         public const VbStrConv vbLinguisticCasing = VbStrConv.LinguisticCasing;
+        public const VariantType vbLong = VariantType.Long;
         public const DateFormat vbLongDate = DateFormat.LongDate;
         public const DateFormat vbLongTime = DateFormat.LongTime;
         public const VbStrConv vbLowerCase = VbStrConv.Lowercase;
+        public const CallType vbMethod = CallType.Method;
+        public const AppWinStyle vbMaximizedFocus = AppWinStyle.MaximizedFocus;
+        public const AppWinStyle vbMinimizedFocus = AppWinStyle.MinimizedFocus;
+        public const AppWinStyle vbMinimizedNoFocus = AppWinStyle.MinimizedNoFocus;
+        public const FirstDayOfWeek vbMonday = FirstDayOfWeek.Monday;
+        public const MsgBoxStyle vbMsgBoxHelp = MsgBoxStyle.MsgBoxHelp;
+        public const MsgBoxStyle vbMsgBoxRight = MsgBoxStyle.MsgBoxRight;
+        public const MsgBoxStyle vbMsgBoxRtlReading = MsgBoxStyle.MsgBoxRtlReading;
+        public const MsgBoxStyle vbMsgBoxSetForeground = MsgBoxStyle.MsgBoxSetForeground;
         [System.ObsoleteAttribute("For a carriage return and line feed, use vbCrLf.  For the current platform's newline, use System.Environment.NewLine.")]
         public const VbStrConv vbNarrow = VbStrConv.Narrow;
         public const string vbNewLine = "\r\n";
+        public const MsgBoxResult vbNo = MsgBoxResult.No;
         public const FileAttribute vbNormal = FileAttribute.Normal;
+        public const AppWinStyle vbNormalFocus = AppWinStyle.NormalFocus;
+        public const AppWinStyle vbNormalNoFocus = AppWinStyle.NormalNoFocus;
+        public const VariantType vbNull = VariantType.Null;
         public const string vbNullChar = "\0";
         public const string vbNullString = null;
+        public const VariantType vbObject = VariantType.Object;
+        public const int vbObjectError = unchecked((int)0x80040000);
+        public const MsgBoxResult vbOK = MsgBoxResult.Ok;
+        public const MsgBoxStyle vbOKCancel = MsgBoxStyle.OkCancel;
+        public const MsgBoxStyle vbOKOnly = MsgBoxStyle.ApplicationModal;
         public const VbStrConv vbProperCase = VbStrConv.ProperCase;
+        public const MsgBoxStyle vbQuestion = MsgBoxStyle.Question;
         public const FileAttribute vbReadOnly = FileAttribute.ReadOnly;
+        public const MsgBoxResult vbRetry = MsgBoxResult.Retry;
+        public const MsgBoxStyle vbRetryCancel = MsgBoxStyle.RetryCancel;
+        public const FirstDayOfWeek vbSaturday = FirstDayOfWeek.Saturday;
+        public const CallType vbSet = CallType.Set;
         public const DateFormat vbShortDate = DateFormat.ShortDate;
         public const DateFormat vbShortTime = DateFormat.ShortTime;
         public const VbStrConv vbSimplifiedChinese = VbStrConv.SimplifiedChinese;
+        public const VariantType vbSingle = VariantType.Single;
+        public const VariantType vbString = VariantType.String;
+        public const FirstDayOfWeek vbSunday = FirstDayOfWeek.Sunday;
         public const FileAttribute vbSystem = FileAttribute.System;
+        public const MsgBoxStyle vbSystemModal = MsgBoxStyle.SystemModal;
         public const string vbTab = "\t";
         public const Microsoft.VisualBasic.CompareMethod vbTextCompare = Microsoft.VisualBasic.CompareMethod.Text;
+        public const FirstDayOfWeek vbThursday = FirstDayOfWeek.Thursday;
         public const VbStrConv vbTraditionalChinese = VbStrConv.TraditionalChinese;
         public const TriState vbTrue = TriState.True;
+        public const FirstDayOfWeek vbTuesday = FirstDayOfWeek.Tuesday;
         public const VbStrConv vbUpperCase = VbStrConv.Uppercase;
         public const TriState vbUseDefault = TriState.UseDefault;
+        public const VariantType vbUserDefinedType = VariantType.UserDefinedType;
+        public const FirstWeekOfYear vbUseSystem = FirstWeekOfYear.System;
+        public const FirstDayOfWeek vbUseSystemDayOfWeek = FirstDayOfWeek.System;
+        public const VariantType vbVariant = VariantType.Variant;
         public const string vbVerticalTab = "\v";
         public const FileAttribute vbVolume = FileAttribute.Volume;
+        public const FirstDayOfWeek vbWednesday = FirstDayOfWeek.Wednesday;
         public const VbStrConv vbWide = VbStrConv.Wide;
+        public const MsgBoxResult vbYes = MsgBoxResult.Yes;
+        public const MsgBoxStyle vbYesNo = MsgBoxStyle.YesNo;
+        public const MsgBoxStyle vbYesNoCancel = MsgBoxStyle.YesNoCancel;
     }
     public sealed partial class ControlChars
     {
@@ -175,8 +249,31 @@ namespace Microsoft.VisualBasic
     public sealed partial class DateAndTime
     {
         internal DateAndTime() { }
+        public static System.DateTime DateAdd(DateInterval Interval, double Number, System.DateTime DateValue) { throw null; }
+        public static System.DateTime DateAdd(string Interval, double Number, object DateValue) { throw null; }
+        public static long DateDiff(DateInterval Interval, System.DateTime Date1, System.DateTime Date2, FirstDayOfWeek DayOfWeek = FirstDayOfWeek.Sunday, FirstWeekOfYear WeekOfYear = FirstWeekOfYear.Jan1) { throw null; }
+        public static long DateDiff(string Interval, object Date1, object Date2, FirstDayOfWeek DayOfWeek = FirstDayOfWeek.Sunday, FirstWeekOfYear WeekOfYear = FirstWeekOfYear.Jan1) { throw null; }
+        public static int DatePart(DateInterval Interval, System.DateTime DateValue, FirstDayOfWeek FirstDayOfWeekValue = FirstDayOfWeek.Sunday, FirstWeekOfYear FirstWeekOfYearValue = FirstWeekOfYear.Jan1) { throw null; }
+        public static int DatePart(string Interval, object DateValue, FirstDayOfWeek DayOfWeek = FirstDayOfWeek.Sunday, FirstWeekOfYear WeekOfYear = FirstWeekOfYear.Jan1) { throw null; }
+        public static System.DateTime DateSerial(int Year, int Month, int Day) { throw null; }
+        public static string DateString { get { throw null; } set { } }
+        public static System.DateTime DateValue(string StringDate) { throw null; }
+        public static int Day(System.DateTime DateValue) { throw null; }
+        public static int Hour(System.DateTime TimeValue) { throw null; }
+        public static int Minute(System.DateTime TimeValue) { throw null; }
+        public static int Month(System.DateTime DateValue) { throw null; }
+        public static string MonthName(int Month, bool Abbreviate = false) { throw null; }
         public static System.DateTime Now { get { throw null; } }
-        public static System.DateTime Today { get { throw null; } }
+        public static int Second(System.DateTime TimeValue) { throw null; }
+        public static System.DateTime TimeOfDay { get { throw null; } set { } }
+        public static double Timer { get { throw null; } }
+        public static System.DateTime TimeSerial(int Hour, int Minute, int Second) { throw null; }
+        public static string TimeString { get { throw null; } set { } }
+        public static System.DateTime TimeValue(string StringTime) { throw null; }
+        public static System.DateTime Today { get { throw null; } set { } }
+        public static int Weekday(System.DateTime DateValue, FirstDayOfWeek DayOfWeek = FirstDayOfWeek.Sunday) { throw null; }
+        public static string WeekdayName(int Weekday, bool Abbreviate = false, FirstDayOfWeek FirstDayOfWeekValue = FirstDayOfWeek.System) { throw null; }
+        public static int Year(System.DateTime DateValue) { throw null; }
     }
     public enum DateFormat
     {
@@ -186,6 +283,24 @@ namespace Microsoft.VisualBasic
         ShortDate = 2,
         ShortTime = 4,
     }
+    public enum DateInterval
+    {
+        DayOfYear = 3,
+        Day = 4,
+        Hour = 7,
+        Minute = 8,
+        Month = 2,
+        Quarter = 1,
+        Second = 9,
+        Weekday = 6,
+        WeekOfYear = 5,
+        Year = 0,
+    }
+    public enum DueDate
+    {
+        BegOfPeriod = 1,
+        EndOfPeriod = 0,
+    }
     public sealed partial class ErrObject
     {
         internal ErrObject() { }
@@ -297,6 +412,24 @@ namespace Microsoft.VisualBasic
         public static void Write(int FileNumber, params object[] Output) { }
         public static void WriteLine(int FileNumber, params object[] Output) { }
     }
+    public enum FirstDayOfWeek
+    {
+        Friday = 6,
+        Monday = 2,
+        Saturday = 7,
+        Sunday = 1,
+        System = 0,
+        Thursday = 5,
+        Tuesday = 3,
+        Wednesday = 4,
+    }
+    public enum FirstWeekOfYear
+    {
+        FirstFourDays = 2,
+        FirstFullWeek = 3,
+        Jan1 = 1,
+        System = 0,
+    }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
     [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
     public sealed partial class HideModuleNameAttribute : System.Attribute
@@ -330,6 +463,39 @@ namespace Microsoft.VisualBasic
         internal Interaction() { }
         public static object CallByName(object ObjectRef, string ProcName, CallType UseCallType, params object[] Args) { throw null; }
     }
+    public enum MsgBoxResult
+    {
+        Abort = 3,
+        Cancel = 2,
+        Ignore = 5,
+        Ok = 1,
+        Retry = 4,
+        No = 7,
+        Yes = 6,
+    }
+    [System.FlagsAttribute]
+    public enum MsgBoxStyle
+    {
+        AbortRetryIgnore = 2,
+        ApplicationModal = 0,
+        Critical = 16,
+        DefaultButton1 = 0,
+        DefaultButton2 = 256,
+        DefaultButton3 = 512,
+        Exclamation = 48,
+        Information = 64,
+        MsgBoxHelp = 16384,
+        MsgBoxRight = 524288,
+        MsgBoxRtlReading = 1048576,
+        MsgBoxSetForeground = 65536,
+        OkCancel = 1,
+        OkOnly = 0,
+        Question = 32,
+        RetryCancel = 5,
+        SystemModal = 4096,
+        YesNo = 4,
+        YesNoCancel = 3,
+    }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
     [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
     public sealed partial class MyGroupCollectionAttribute : System.Attribute
index c8413b9..4efe986 100644 (file)
@@ -23,6 +23,7 @@
     <Compile Include="Microsoft\VisualBasic\FileIO\FileSystem.Windows.vb" />
     <Compile Include="Microsoft\VisualBasic\Helpers\NativeMethods.vb" />
     <Compile Include="Microsoft\VisualBasic\Helpers\NativeTypes.vb" />
+    <Compile Include="Microsoft\VisualBasic\Helpers\SafeNativeMethods.vb" />
     <Compile Include="Microsoft\VisualBasic\Helpers\UnsafeNativeMethods.vb" />
   </ItemGroup>
     <ItemGroup Condition="'$(TargetsWindows)' != 'true'">
@@ -34,7 +35,6 @@
     <Compile Include="Microsoft\VisualBasic\ApplicationServices\StartupNextInstanceEventArgs.vb" />
     <Compile Include="Microsoft\VisualBasic\ApplicationServices\UnhandledExceptionEventArgs.vb" />
     <Compile Include="Microsoft\VisualBasic\ApplicationServices\User.vb" />
-    <Compile Include="Microsoft\VisualBasic\CallType.vb" />
     <Compile Include="Microsoft\VisualBasic\Collection.vb" />
     <Compile Include="Microsoft\VisualBasic\ComClassAttribute.vb" />
     <Compile Include="Microsoft\VisualBasic\CompilerServices\BooleanType.vb" />
     <Compile Include="Microsoft\VisualBasic\MyServices\RegistryProxy.vb" />
     <Compile Include="Microsoft\VisualBasic\MyServices\SpecialDirectoriesProxy.vb" />
     <Compile Include="Microsoft\VisualBasic\Strings.vb" />
-    <Compile Include="Microsoft\VisualBasic\VariantType.vb" />
     <Compile Include="Microsoft\VisualBasic\VBFixedArrayAttribute.vb" />
     <Compile Include="Microsoft\VisualBasic\VBFixedStringAttribute.vb" />
     <Compile Include="Microsoft\VisualBasic\VBMath.vb" />
diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CallType.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CallType.vb
deleted file mode 100644 (file)
index 97412f0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-' Licensed to the .NET Foundation under one or more agreements.
-' The .NET Foundation licenses this file to you under the MIT license.
-' See the LICENSE file in the project root for more information.
-
-Namespace Global.Microsoft.VisualBasic
-    Public Enum CallType
-        Method = 1
-        [Get] = 2
-        [Let] = 4
-        [Set] = 8
-    End Enum
-End Namespace
index 37b6ade..06fd03f 100644 (file)
@@ -3,13 +3,10 @@
 ' See the LICENSE file in the project root for more information.
 
 Imports System
-Imports System.Security
 Imports System.Text
 Imports System.Globalization
-Imports System.Runtime.InteropServices
 Imports System.Reflection
 Imports System.Diagnostics
-Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
 Imports Microsoft.VisualBasic.CompilerServices.Symbols
 
 Namespace Microsoft.VisualBasic.CompilerServices
@@ -22,7 +19,7 @@ Namespace Microsoft.VisualBasic.CompilerServices
         Friend Const FACILITY_RPC As Integer = &H10000I
         Friend Const FACILITY_ITF As Integer = &H40000I
         Friend Const SCODE_FACILITY As Integer = &H1FFF0000I
-        Private Const s_ERROR_INVALID_PARAMETER As Integer = 87
+        Private Const ERROR_INVALID_PARAMETER As Integer = 87
 
         Friend Const chPeriod As Char = "."c
         Friend Const chSpace As Char = ChrW(32)
index 76f7fdf..f3b3af7 100644 (file)
@@ -4,10 +4,13 @@
 
 Imports System
 Imports System.Diagnostics
+Imports System.Globalization
 Imports System.Linq
 Imports System.Linq.Expressions
-Imports System.Text
 Imports System.Reflection
+Imports System.Runtime.InteropServices
+Imports System.Security
+Imports System.Text
 
 Namespace Global.Microsoft.VisualBasic.CompilerServices
     <Global.System.Diagnostics.DebuggerNonUserCode()>
@@ -15,6 +18,66 @@ Namespace Global.Microsoft.VisualBasic.CompilerServices
     Partial Public Class Utils
         Private Sub New()
         End Sub
+
+        <Diagnostics.DebuggerHiddenAttribute()>
+        Friend Shared Sub SetTime(ByVal dtTime As DateTime)
+#If PLATFORM_WINDOWS Then
+            Dim systime As New NativeTypes.SystemTime
+
+            SafeNativeMethods.GetLocalTime(systime)
+
+            systime.wHour = CShort(dtTime.Hour)
+            systime.wMinute = CShort(dtTime.Minute)
+            systime.wSecond = CShort(dtTime.Second)
+            systime.wMilliseconds = CShort(dtTime.Millisecond)
+
+            If UnsafeNativeMethods.SetLocalTime(systime) = 0 Then
+                If Marshal.GetLastWin32Error() = ERROR_INVALID_PARAMETER Then
+                    Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue))
+                Else
+                    Throw New SecurityException(GetResourceString(SR.SetLocalTimeFailure))
+                End If
+            End If
+#Else
+            Throw New PlatformNotSupportedException()
+#End If
+        End Sub
+
+        <Diagnostics.DebuggerHiddenAttribute()>
+        Friend Shared Sub SetDate(ByVal vDate As DateTime)
+#If PLATFORM_WINDOWS Then
+            Dim systime As New NativeTypes.SystemTime
+
+            SafeNativeMethods.GetLocalTime(systime)
+
+            systime.wYear = CShort(vDate.Year)
+            systime.wMonth = CShort(vDate.Month)
+            systime.wDay = CShort(vDate.Day)
+
+            If UnsafeNativeMethods.SetLocalTime(systime) = 0 Then
+                If Marshal.GetLastWin32Error() = ERROR_INVALID_PARAMETER Then
+                    Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue))
+                Else
+                    Throw New SecurityException(GetResourceString(SR.SetLocalDateFailure))
+                End If
+            End If
+#Else
+            Throw New PlatformNotSupportedException()
+#End If
+        End Sub
+
+        Friend Shared Function GetDateTimeFormatInfo() As DateTimeFormatInfo
+            Return System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat
+        End Function
+
+        Friend Shared Function GetFileIOEncoding() As Encoding
+            Return System.Text.Encoding.Default
+        End Function
+
+        Friend Shared Function GetLocaleCodePage() As Integer
+            Return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage
+        End Function
+
         Public Shared Function CopyArray(arySrc As Global.System.Array, aryDest As Global.System.Array) As Global.System.Array
             If arySrc Is Nothing Then
                 Return aryDest
@@ -54,14 +117,6 @@ Namespace Global.Microsoft.VisualBasic.CompilerServices
             Return aryDest
         End Function
 
-        Friend Shared Function GetFileIOEncoding() As Encoding
-            Return System.Text.Encoding.Default
-        End Function
-
-        Friend Shared Function GetLocaleCodePage() As Integer
-            Return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ANSICodePage
-        End Function
-
     End Class
 
     Friend Module ReflectionExtensions
index 8f0babe..2f43227 100644 (file)
@@ -8,6 +8,7 @@ Namespace Global.Microsoft.VisualBasic
     Public Module Constants
 
         Public Const vbCrLf As String = ChrW(13) & ChrW(10)
+        Public Const vbObjectError As Integer = &H80040000I
         <Global.System.Obsolete("For a carriage return and line feed, use vbCrLf.  For the current platform's newline, use System.Environment.NewLine.")>
         Public Const vbNewLine As String = ChrW(13) & ChrW(10)
         Public Const vbCr As String = ChrW(13)
@@ -19,6 +20,20 @@ Namespace Global.Microsoft.VisualBasic
         Public Const vbNullChar As String = ChrW(0)
         Public Const vbNullString As String = Nothing
 
+        'AppWinStyle
+        Public Const vbHide As AppWinStyle = AppWinStyle.Hide
+        Public Const vbNormalFocus As AppWinStyle = AppWinStyle.NormalFocus
+        Public Const vbMinimizedFocus As AppWinStyle = AppWinStyle.MinimizedFocus
+        Public Const vbMaximizedFocus As AppWinStyle = AppWinStyle.MaximizedFocus
+        Public Const vbNormalNoFocus As AppWinStyle = AppWinStyle.NormalNoFocus
+        Public Const vbMinimizedNoFocus As AppWinStyle = AppWinStyle.MinimizedNoFocus
+
+        'vbCallType Enum values
+        Public Const vbMethod As CallType = CallType.Method
+        Public Const vbGet As CallType = CallType.Get
+        Public Const vbLet As CallType = CallType.Let
+        Public Const vbSet As CallType = CallType.Set
+
         'vbCompareMethod enum values
         Public Const vbBinaryCompare As CompareMethod = CompareMethod.Binary
         Public Const vbTextCompare As CompareMethod = CompareMethod.Text
@@ -30,6 +45,16 @@ Namespace Global.Microsoft.VisualBasic
         Public Const vbLongTime As DateFormat = DateFormat.LongTime
         Public Const vbShortTime As DateFormat = DateFormat.ShortTime
 
+        'vbDayOfWeek
+        Public Const vbUseSystemDayOfWeek As FirstDayOfWeek = FirstDayOfWeek.System
+        Public Const vbSunday As FirstDayOfWeek = FirstDayOfWeek.Sunday
+        Public Const vbMonday As FirstDayOfWeek = FirstDayOfWeek.Monday
+        Public Const vbTuesday As FirstDayOfWeek = FirstDayOfWeek.Tuesday
+        Public Const vbWednesday As FirstDayOfWeek = FirstDayOfWeek.Wednesday
+        Public Const vbThursday As FirstDayOfWeek = FirstDayOfWeek.Thursday
+        Public Const vbFriday As FirstDayOfWeek = FirstDayOfWeek.Friday
+        Public Const vbSaturday As FirstDayOfWeek = FirstDayOfWeek.Saturday
+
         'FileAttribute
         Public Const vbNormal As FileAttribute = FileAttribute.Normal
         Public Const vbReadOnly As FileAttribute = FileAttribute.ReadOnly
@@ -39,6 +64,12 @@ Namespace Global.Microsoft.VisualBasic
         Public Const vbDirectory As FileAttribute = FileAttribute.Directory
         Public Const vbArchive As FileAttribute = FileAttribute.Archive
 
+        'vbFirstWeekOfYear
+        Public Const vbUseSystem As FirstWeekOfYear = FirstWeekOfYear.System
+        Public Const vbFirstJan1 As FirstWeekOfYear = FirstWeekOfYear.Jan1
+        Public Const vbFirstFourDays As FirstWeekOfYear = FirstWeekOfYear.FirstFourDays
+        Public Const vbFirstFullWeek As FirstWeekOfYear = FirstWeekOfYear.FirstFullWeek
+
         'vbStrConv
         Public Const vbUpperCase As VbStrConv = VbStrConv.Uppercase
         Public Const vbLowerCase As VbStrConv = VbStrConv.Lowercase
@@ -56,6 +87,55 @@ Namespace Global.Microsoft.VisualBasic
         Public Const vbTrue As TriState = TriState.True
         Public Const vbFalse As TriState = TriState.False
 
+        'VariantType
+        Public Const vbEmpty As VariantType = VariantType.Empty
+        Public Const vbNull As VariantType = VariantType.Null
+        Public Const vbInteger As VariantType = VariantType.Integer
+        Public Const vbLong As VariantType = VariantType.Long
+        Public Const vbSingle As VariantType = VariantType.Single
+        Public Const vbDouble As VariantType = VariantType.Double
+        Public Const vbCurrency As VariantType = VariantType.Currency
+        Public Const vbDate As VariantType = VariantType.Date
+        Public Const vbString As VariantType = VariantType.String
+        Public Const vbObject As VariantType = VariantType.Object
+        Public Const vbBoolean As VariantType = VariantType.Boolean
+        Public Const vbVariant As VariantType = VariantType.Variant
+        Public Const vbDecimal As VariantType = VariantType.Decimal
+        Public Const vbByte As VariantType = VariantType.Byte
+        Public Const vbUserDefinedType As VariantType = VariantType.UserDefinedType
+        Public Const vbArray As VariantType = VariantType.Array
+
+        'MsgBoxResult
+        Public Const vbOK As MsgBoxResult = MsgBoxResult.Ok
+        Public Const vbCancel As MsgBoxResult = MsgBoxResult.Cancel
+        Public Const vbAbort As MsgBoxResult = MsgBoxResult.Abort
+        Public Const vbRetry As MsgBoxResult = MsgBoxResult.Retry
+        Public Const vbIgnore As MsgBoxResult = MsgBoxResult.Ignore
+        Public Const vbYes As MsgBoxResult = MsgBoxResult.Yes
+        Public Const vbNo As MsgBoxResult = MsgBoxResult.No
+
+        'MsgBoxStyle
+        'You may BitOr one value from each group
+        Public Const vbOKOnly As MsgBoxStyle = MsgBoxStyle.OkOnly
+        Public Const vbOKCancel As MsgBoxStyle = MsgBoxStyle.OkCancel
+        Public Const vbAbortRetryIgnore As MsgBoxStyle = MsgBoxStyle.AbortRetryIgnore
+        Public Const vbYesNoCancel As MsgBoxStyle = MsgBoxStyle.YesNoCancel
+        Public Const vbYesNo As MsgBoxStyle = MsgBoxStyle.YesNo
+        Public Const vbRetryCancel As MsgBoxStyle = MsgBoxStyle.RetryCancel
+        Public Const vbCritical As MsgBoxStyle = MsgBoxStyle.Critical
+        Public Const vbQuestion As MsgBoxStyle = MsgBoxStyle.Question
+        Public Const vbExclamation As MsgBoxStyle = MsgBoxStyle.Exclamation
+        Public Const vbInformation As MsgBoxStyle = MsgBoxStyle.Information
+        Public Const vbDefaultButton1 As MsgBoxStyle = MsgBoxStyle.DefaultButton1
+        Public Const vbDefaultButton2 As MsgBoxStyle = MsgBoxStyle.DefaultButton2
+        Public Const vbDefaultButton3 As MsgBoxStyle = MsgBoxStyle.DefaultButton3
+        Public Const vbApplicationModal As MsgBoxStyle = MsgBoxStyle.ApplicationModal
+        Public Const vbSystemModal As MsgBoxStyle = MsgBoxStyle.SystemModal
+        Public Const vbMsgBoxHelp As MsgBoxStyle = MsgBoxStyle.MsgBoxHelp
+        Public Const vbMsgBoxRight As MsgBoxStyle = MsgBoxStyle.MsgBoxRight
+        Public Const vbMsgBoxRtlReading As MsgBoxStyle = MsgBoxStyle.MsgBoxRtlReading
+        Public Const vbMsgBoxSetForeground As MsgBoxStyle = MsgBoxStyle.MsgBoxSetForeground
+
     End Module
 
 End Namespace
index afff190..bc42c49 100644 (file)
 ' See the LICENSE file in the project root for more information.
 
 Imports System
+Imports System.Globalization
+Imports Microsoft.VisualBasic.CompilerServices
+Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
+Imports Microsoft.VisualBasic.CompilerServices.Utils
 
 Namespace Microsoft.VisualBasic
     Public Module DateAndTime
+
+        Private AcceptedDateFormatsDBCS() As String = {"yyyy-M-d", "y-M-d", "yyyy/M/d", "y/M/d"}
+        Private AcceptedDateFormatsSBCS() As String = {"M-d-yyyy", "M-d-y", "M/d/yyyy", "M/d/y"}
+
+        '============================================================================
+        ' Date/Time Properties
+        '============================================================================
+        Public Property Today() As DateTime
+            Get
+                Return DateTime.Today
+            End Get
+            Set(ByVal Value As DateTime)
+                SetDate(Value)
+            End Set
+        End Property
+
         Public ReadOnly Property Now As DateTime
             Get
                 Return DateTime.Now
             End Get
         End Property
 
-        Public ReadOnly Property Today As DateTime
+        Public Property TimeOfDay() As DateTime
             Get
-                Return DateTime.Today
+                Dim Ticks As Int64 = DateTime.Now.TimeOfDay.Ticks
+
+                'Truncate to the nearest second
+                Return New DateTime(Ticks - Ticks Mod TimeSpan.TicksPerSecond)
+            End Get
+            Set(ByVal Value As DateTime)
+                SetTime(Value)
+            End Set
+        End Property
+
+        ' TimeString (replaces Time$)
+        Public Property TimeString() As String
+            'Locale agnostic, Always returns 24hr clock
+            Get
+                Return (New DateTime(DateTime.Now.TimeOfDay.Ticks)).ToString("HH:mm:ss", GetInvariantCultureInfo())
+            End Get
+            Set(ByVal Value As String)
+                Dim dt As Date
+
+                Try
+                    dt = CompilerServices.DateType.FromString(Value, GetInvariantCultureInfo())
+                Catch ex As StackOverflowException
+                    Throw ex
+                Catch ex As OutOfMemoryException
+                    Throw ex
+                Catch ex As System.Threading.ThreadAbortException
+                    Throw ex
+                Catch
+                    Throw VbMakeException(New InvalidCastException(GetResourceString(SR.InvalidCast_FromStringTo, Left(Value, 32), "Date")), vbErrors.IllegalFuncCall)
+                End Try
+
+                SetTime(dt)
+            End Set
+        End Property
+
+        Private Function IsDBCSCulture() As Boolean
+#If PLATFORM_WINDOWS Then
+            'This function is apparently trying to determine a different default for East Asian systems.
+            If System.Runtime.InteropServices.Marshal.SystemMaxDBCSCharSize = 1 Then
+                Return False
+            End If
+            Return True
+#Else
+            ' Emulate IsDBCSCulture of .NET 3.5 using CultureInfo
+            Dim langName As String = System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName
+            Return String.Equals(langName, "zh", StringComparison.OrdinalIgnoreCase) OrElse _
+                String.Equals(langName, "ko", StringComparison.OrdinalIgnoreCase) OrElse _
+                String.Equals(langName, "ja", StringComparison.OrdinalIgnoreCase)
+#End If
+        End Function
+
+        Public Property DateString() As String
+            ' DateString (replaces Date$)
+            'Returns yyyy-MM-dd for DBCS locale
+            'Returns MM-dd-yyyy for non-DBCS locale
+            Get
+                If IsDBCSCulture() Then
+                    Return DateTime.Today.ToString("yyyy\-MM\-dd", GetInvariantCultureInfo())
+                Else
+                    Return DateTime.Today.ToString("MM\-dd\-yyyy", GetInvariantCultureInfo())
+                End If
+            End Get
+            Set(ByVal Value As String)
+                Dim NewDate As Date
+
+                Try
+                    Dim TmpValue As String = ToHalfwidthNumbers(Value, GetCultureInfo())
+                    If IsDBCSCulture() Then
+                        NewDate = DateTime.ParseExact(TmpValue, AcceptedDateFormatsDBCS, GetInvariantCultureInfo(), DateTimeStyles.AllowWhiteSpaces)
+                    Else
+                        NewDate = DateTime.ParseExact(TmpValue, AcceptedDateFormatsSBCS, GetInvariantCultureInfo(), DateTimeStyles.AllowWhiteSpaces)
+                    End If
+                Catch ex As StackOverflowException
+                    Throw ex
+                Catch ex As OutOfMemoryException
+                    Throw ex
+                Catch ex As System.Threading.ThreadAbortException
+                    Throw ex
+                Catch
+                    Throw VbMakeException(New InvalidCastException(GetResourceString(SR.InvalidCast_FromStringTo, Left(Value, 32), "Date")), vbErrors.IllegalFuncCall)
+                End Try
+
+                SetDate(NewDate)
+
+            End Set
+        End Property
+
+        Public ReadOnly Property Timer() As Double
+            Get
+                'Returns number of seconds past Midnight
+                Return (System.DateTime.Now.Ticks Mod System.TimeSpan.TicksPerDay) /
+                        (TimeSpan.TicksPerMillisecond * 1000)
             End Get
         End Property
+
+        Private ReadOnly Property CurrentCalendar() As Calendar
+            Get
+                Return Threading.Thread.CurrentThread.CurrentCulture.Calendar
+            End Get
+        End Property
+
+        '============================================================================
+        ' Date manipulation functions.
+        '============================================================================
+        Public Function DateAdd(ByVal Interval As DateInterval,
+            ByVal Number As Double,
+            ByVal DateValue As DateTime) As DateTime
+            Dim lNumber As Integer
+
+            lNumber = CInt(Fix(Number))
+
+            Select Case Interval
+                Case DateInterval.Year
+                    Return CurrentCalendar.AddYears(DateValue, lNumber)
+                Case DateInterval.Month
+                    Return CurrentCalendar.AddMonths(DateValue, lNumber)
+                Case DateInterval.Day,
+                     DateInterval.DayOfYear,
+                     DateInterval.Weekday
+                    Return DateValue.AddDays(lNumber)
+                Case DateInterval.WeekOfYear
+                    Return DateValue.AddDays(lNumber * 7.0#)
+                Case DateInterval.Hour
+                    Return DateValue.AddHours(lNumber)
+                Case DateInterval.Minute
+                    Return DateValue.AddMinutes(lNumber)
+                Case DateInterval.Second
+                    Return DateValue.AddSeconds(lNumber)
+                Case DateInterval.Quarter
+                    Return DateValue.AddMonths(lNumber * 3)
+            End Select
+
+            Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Interval"))
+        End Function
+
+        Public Function DateDiff(ByVal Interval As DateInterval,
+            ByVal Date1 As DateTime,
+            ByVal Date2 As DateTime,
+            Optional ByVal DayOfWeek As FirstDayOfWeek = FirstDayOfWeek.Sunday,
+            Optional ByVal WeekOfYear As FirstWeekOfYear = FirstWeekOfYear.Jan1) As Long
+
+            Dim tm As TimeSpan
+            Dim cal As Calendar
+
+            tm = Date2.Subtract(Date1)
+
+            Select Case Interval
+                Case DateInterval.Year
+                    cal = CurrentCalendar
+                    Return cal.GetYear(Date2) - cal.GetYear(Date1)
+                Case DateInterval.Month
+                    cal = CurrentCalendar
+                    Return (cal.GetYear(Date2) - cal.GetYear(Date1)) * 12 + cal.GetMonth(Date2) - cal.GetMonth(Date1)
+                Case DateInterval.Day,
+                     DateInterval.DayOfYear
+                    Return CLng(Fix(tm.TotalDays()))
+                Case DateInterval.Hour
+                    Return CLng(Fix(tm.TotalHours()))
+                Case DateInterval.Minute
+                    Return CLng(Fix(tm.TotalMinutes()))
+                Case DateInterval.Second
+                    Return CLng(Fix(tm.TotalSeconds()))
+                Case DateInterval.WeekOfYear
+                    Date1 = Date1.AddDays(-GetDayOfWeek(Date1, DayOfWeek))
+                    Date2 = Date2.AddDays(-GetDayOfWeek(Date2, DayOfWeek))
+                    tm = Date2.Subtract(Date1)
+                    Return CLng(Fix(tm.TotalDays())) \ 7
+                Case DateInterval.Weekday
+                    Return CLng(Fix(tm.TotalDays())) \ 7
+                Case DateInterval.Quarter
+                    cal = CurrentCalendar
+                    Return (cal.GetYear(Date2) - cal.GetYear(Date1)) * 4 + (cal.GetMonth(Date2) - 1) \ 3 - (cal.GetMonth(Date1) - 1) \ 3
+            End Select
+
+            Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Interval"))
+        End Function
+
+        Private Function GetDayOfWeek(ByVal dt As Date, ByVal weekdayFirst As FirstDayOfWeek) As Integer
+            If (weekdayFirst < FirstDayOfWeek.System OrElse weekdayFirst > FirstDayOfWeek.Saturday) Then
+                Throw VbMakeException(vbErrors.IllegalFuncCall)
+            End If
+
+            ' If FirstWeekDay is 0, get offset from NLS.
+            If (weekdayFirst = FirstDayOfWeek.System) Then
+                weekdayFirst = CType(GetDateTimeFormatInfo().FirstDayOfWeek + 1, FirstDayOfWeek)
+            End If
+
+            Return (dt.DayOfWeek - weekdayFirst + 8) Mod 7 + 1
+        End Function
+
+        Public Function DatePart(ByVal Interval As DateInterval, ByVal DateValue As DateTime,
+            Optional ByVal FirstDayOfWeekValue As FirstDayOfWeek = vbSunday,
+            Optional ByVal FirstWeekOfYearValue As FirstWeekOfYear = vbFirstJan1) As Integer
+
+            'Get the part asked for
+            Select Case Interval
+                Case DateInterval.Year
+                    Return CurrentCalendar.GetYear(DateValue)
+                Case DateInterval.Month
+                    Return CurrentCalendar.GetMonth(DateValue)
+                Case DateInterval.Day
+                    Return CurrentCalendar.GetDayOfMonth(DateValue)
+                Case DateInterval.Hour
+                    Return CurrentCalendar.GetHour(DateValue)
+                Case DateInterval.Minute
+                    Return CurrentCalendar.GetMinute(DateValue)
+                Case DateInterval.Second
+                    Return CurrentCalendar.GetSecond(DateValue)
+                Case DateInterval.Weekday
+                    Return Weekday(DateValue, FirstDayOfWeekValue)
+                Case DateInterval.WeekOfYear
+                    Dim WeekRule As CalendarWeekRule
+                    Dim Day As DayOfWeek
+
+                    If FirstDayOfWeekValue = vbUseSystemDayOfWeek Then
+                        Day = GetCultureInfo().DateTimeFormat.FirstDayOfWeek
+                    Else
+                        Day = CType(FirstDayOfWeekValue - 1, DayOfWeek)
+                    End If
+
+                    Select Case FirstWeekOfYearValue
+                        Case vbUseSystem
+                            WeekRule = GetCultureInfo().DateTimeFormat.CalendarWeekRule
+                        Case vbFirstJan1
+                            WeekRule = CalendarWeekRule.FirstDay
+                        Case vbFirstFourDays
+                            WeekRule = CalendarWeekRule.FirstFourDayWeek
+                        Case vbFirstFullWeek
+                            WeekRule = CalendarWeekRule.FirstFullWeek
+                    End Select
+
+                    Return CurrentCalendar.GetWeekOfYear(DateValue, WeekRule, Day)
+                Case DateInterval.Quarter
+                    Return ((DateValue.Month - 1) \ 3) + 1
+                Case DateInterval.DayOfYear
+                    Return CurrentCalendar.GetDayOfYear(DateValue)
+            End Select
+
+            Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Interval"))
+        End Function
+
+        Public Function DateAdd(ByVal Interval As String,
+            ByVal Number As Double,
+            ByVal DateValue As Object) As DateTime
+
+            Dim dt1 As Date
+
+            Try
+                dt1 = CDate(DateValue)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw New InvalidCastException(GetResourceString(SR.Argument_InvalidDateValue1, "DateValue"))
+            End Try
+
+            Return DateAdd(DateIntervalFromString(Interval), Number, dt1)
+        End Function
+
+        Public Function DateDiff(ByVal Interval As String,
+            ByVal Date1 As Object,
+            ByVal Date2 As Object,
+            Optional ByVal DayOfWeek As FirstDayOfWeek = FirstDayOfWeek.Sunday,
+            Optional ByVal WeekOfYear As FirstWeekOfYear = FirstWeekOfYear.Jan1) As Long
+
+            Dim dt1, dt2 As Date
+
+            Try
+                dt1 = CDate(Date1)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw New InvalidCastException(GetResourceString(SR.Argument_InvalidDateValue1, "Date1"))
+            End Try
+            Try
+                dt2 = CDate(Date2)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw New InvalidCastException(GetResourceString(SR.Argument_InvalidDateValue1, "Date2"))
+            End Try
+
+            Return DateDiff(DateIntervalFromString(Interval), dt1, dt2, DayOfWeek, WeekOfYear)
+        End Function
+
+        Public Function DatePart(ByVal Interval As String, ByVal DateValue As Object,
+            Optional ByVal DayOfWeek As FirstDayOfWeek = FirstDayOfWeek.Sunday,
+            Optional ByVal WeekOfYear As FirstWeekOfYear = FirstWeekOfYear.Jan1) As Integer
+
+            Dim dt1 As Date
+
+            Try
+                dt1 = CDate(DateValue)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw New InvalidCastException(GetResourceString(SR.Argument_InvalidDateValue1, "DateValue"))
+            End Try
+
+            Return DatePart(DateIntervalFromString(Interval), dt1, DayOfWeek, WeekOfYear)
+        End Function
+
+        Private Function DateIntervalFromString(ByVal Interval As String) As DateInterval
+            If Interval IsNot Nothing Then
+                Interval = Interval.ToUpperInvariant()
+            End If
+
+            Select Case Interval
+                Case "YYYY"
+                    Return DateInterval.Year
+                Case "Y"
+                    Return DateInterval.DayOfYear
+                Case "M"
+                    Return DateInterval.Month
+                Case "D"
+                    Return DateInterval.Day
+                Case "H"
+                    Return DateInterval.Hour
+                Case "N"
+                    Return DateInterval.Minute
+                Case "S"
+                    Return DateInterval.Second
+                Case "WW"
+                    Return DateInterval.WeekOfYear
+                Case "W"
+                    Return DateInterval.Weekday
+                Case "Q"
+                    Return DateInterval.Quarter
+                Case Else
+                    Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Interval"))
+            End Select
+        End Function
+
+        '============================================================================
+        ' Date value functions.
+        '============================================================================
+        Public Function DateSerial(ByVal [Year] As Integer, ByVal [Month] As Integer, ByVal [Day] As Integer) As DateTime
+            'We have to handle negative months and days
+            ' so we start with the year and add months and days
+            Dim cal As Calendar = CurrentCalendar
+            Dim Result As DateTime
+
+            If Year < 0 Then
+                Year = cal.GetYear(System.DateTime.Today) + Year
+            ElseIf Year < 100 Then
+                Year = cal.ToFourDigitYear(Year)
+            End If
+
+            '*** BEGIN PERFOPT ***
+            '*** Gregorian Calendar perf optimization
+            '*** The AddMonths/AddDays require excessive conversion to/from ticks
+            '*** so we special case 
+            If TypeOf cal Is GregorianCalendar Then
+                If (Month >= 1 AndAlso Month <= 12) AndAlso (Day >= 1 AndAlso Day <= 28) Then
+                    'Uses 28 so we don't have to use the calendar to obtain
+                    ' the number of days in the month, which is the cause of the
+                    ' extra overhead we are trying to avoid
+                    Return New DateTime(Year, Month, Day)
+                End If
+            End If
+            '*** END PERFOPT ***
+
+            Try
+                Result = cal.ToDateTime(Year, 1, 1, 0, 0, 0, 0)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw VbMakeException(New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Year")), vbErrors.IllegalFuncCall)
+            End Try
+
+            Try
+                Result = cal.AddMonths(Result, Month - 1)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw VbMakeException(New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Month")), vbErrors.IllegalFuncCall)
+            End Try
+
+            Try
+                Result = cal.AddDays(Result, Day - 1)
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw VbMakeException(New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Day")), vbErrors.IllegalFuncCall)
+            End Try
+
+            Return Result
+        End Function
+
+        Public Function TimeSerial(ByVal Hour As Integer, ByVal Minute As Integer, ByVal Second As Integer) As DateTime
+            Const SecondsInDay As Integer = (24 * 60 * 60)
+
+            Dim TotalSeconds As Integer = (Hour * 60 * 60) + (Minute * 60) + Second
+
+            If TotalSeconds < 0 Then
+                'Wrap clock
+                TotalSeconds += SecondsInDay
+            End If
+
+            Return (New DateTime(TotalSeconds * TimeSpan.TicksPerSecond))
+        End Function
+
+        Public Function DateValue(ByVal [StringDate] As String) As DateTime
+
+            Return CDate([StringDate]).Date
+
+        End Function
+
+        Public Function TimeValue(ByVal [StringTime] As String) As DateTime
+
+            Return New DateTime(CDate([StringTime]).Ticks Mod TimeSpan.TicksPerDay)
+
+        End Function
+
+        '============================================================================
+        ' Date/time part functions.
+        '============================================================================
+        Public Function Year(ByVal DateValue As DateTime) As Integer
+            Return CurrentCalendar.GetYear(DateValue)
+        End Function
+
+        Public Function Month(ByVal DateValue As DateTime) As Integer
+            Return CurrentCalendar.GetMonth(DateValue)
+        End Function
+
+        Public Function Day(ByVal DateValue As DateTime) As Integer
+            Return CurrentCalendar.GetDayOfMonth(DateValue)
+        End Function
+
+        Public Function Hour(ByVal [TimeValue] As DateTime) As Integer
+            Return CurrentCalendar.GetHour([TimeValue])
+        End Function
+
+        Public Function Minute(ByVal [TimeValue] As DateTime) As Integer
+            Return CurrentCalendar.GetMinute([TimeValue])
+        End Function
+
+        Public Function Second(ByVal [TimeValue] As DateTime) As Integer
+            Return CurrentCalendar.GetSecond([TimeValue])
+        End Function
+
+        Public Function Weekday(ByVal DateValue As DateTime, Optional ByVal DayOfWeek As FirstDayOfWeek = FirstDayOfWeek.Sunday) As Integer
+            If DayOfWeek = FirstDayOfWeek.System Then
+                '
+                DayOfWeek = CType(DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek + 1, FirstDayOfWeek)
+
+            ElseIf (DayOfWeek < FirstDayOfWeek.Sunday) OrElse (DayOfWeek > FirstDayOfWeek.Saturday) Then
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "DayOfWeek"))
+            End If
+
+            'Get the day from the date
+            Dim iDayOfWeek As Integer
+
+            iDayOfWeek = CurrentCalendar.GetDayOfWeek(DateValue) + 1 ' System.DateTime uses Sunday = 0 thru Satuday = 6
+            Return ((iDayOfWeek - DayOfWeek + 7) Mod 7) + 1
+        End Function
+
+        '============================================================================
+        ' Date name functions.
+        '============================================================================
+
+        Public Function MonthName(ByVal Month As Integer, Optional ByVal Abbreviate As Boolean = False) As String
+            Dim Result As String
+
+            If Month < 1 OrElse Month > 13 Then
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Month"))
+            End If
+
+            If Abbreviate Then
+                Result = GetDateTimeFormatInfo().GetAbbreviatedMonthName(Month)
+            Else
+                Result = GetDateTimeFormatInfo().GetMonthName(Month)
+            End If
+
+            If Result.Length = 0 Then
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Month"))
+            End If
+
+            Return Result
+        End Function
+
+        Public Function WeekdayName(ByVal Weekday As Integer, Optional ByVal Abbreviate As Boolean = False, Optional ByVal FirstDayOfWeekValue As FirstDayOfWeek = FirstDayOfWeek.System) As String
+            Dim dtfi As DateTimeFormatInfo
+            Dim Result As String
+
+            If (Weekday < 1) OrElse (Weekday > 7) Then
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Weekday"))
+            End If
+
+            If (FirstDayOfWeekValue < 0) OrElse (FirstDayOfWeekValue > 7) Then
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "FirstDayOfWeekValue"))
+            End If
+
+            dtfi = CType(GetCultureInfo().GetFormat(GetType(System.Globalization.DateTimeFormatInfo)), DateTimeFormatInfo)  'Returns a read-only object
+
+            If FirstDayOfWeekValue = 0 Then
+                FirstDayOfWeekValue = CType(CInt(dtfi.FirstDayOfWeek) + 1, FirstDayOfWeek)
+            End If
+
+            Try
+                If Abbreviate Then
+                    Result = dtfi.GetAbbreviatedDayName(CType((Weekday + FirstDayOfWeekValue - 2) Mod 7, System.DayOfWeek))
+                Else
+                    Result = dtfi.GetDayName(CType((Weekday + FirstDayOfWeekValue - 2) Mod 7, System.DayOfWeek))
+                End If
+            Catch ex As StackOverflowException
+                Throw ex
+            Catch ex As OutOfMemoryException
+                Throw ex
+            Catch ex As System.Threading.ThreadAbortException
+                Throw ex
+            Catch
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Weekday"))
+            End Try
+
+            If Result.Length = 0 Then
+                Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Weekday"))
+            End If
+
+            Return Result
+        End Function
+
     End Module
 End Namespace
index a00c48e..47b1a1e 100644 (file)
@@ -6,6 +6,45 @@ Imports System
 
 Namespace Global.Microsoft.VisualBasic
 
+    Public Enum VariantType
+        Empty = 0
+        Null = 1
+        [Short] = 2
+        [Integer] = 3
+        [Single] = 4
+        [Double] = 5
+        Currency = 6
+        [Date] = 7
+        [String] = 8
+        [Object] = 9
+        [Error] = 10
+        [Boolean] = 11
+        [Variant] = 12
+        [DataObject] = 13
+        [Decimal] = 14
+        [Byte] = 17
+        [Char] = 18
+        [Long] = 20
+        UserDefinedType = 36
+        Array = 8192
+    End Enum
+
+    Public Enum AppWinStyle As Short
+        Hide = 0
+        NormalFocus = 1
+        MinimizedFocus = 2
+        MaximizedFocus = 3
+        NormalNoFocus = 4
+        MinimizedNoFocus = 6
+    End Enum
+
+    Public Enum CallType
+        Method = 1
+        [Get] = 2
+        [Let] = 4
+        [Set] = 8
+    End Enum
+
     Public Enum CompareMethod
         [Binary] = 0
         [Text] = 1
@@ -19,6 +58,17 @@ Namespace Global.Microsoft.VisualBasic
         ShortTime = 4
     End Enum
 
+    Public Enum FirstDayOfWeek
+        System = 0
+        Sunday = 1
+        Monday = 2
+        Tuesday = 3
+        Wednesday = 4
+        Thursday = 5
+        Friday = 6
+        Saturday = 7
+    End Enum
+
     <Flags()> Public Enum FileAttribute
         [Normal] = 0
         [ReadOnly] = 1
@@ -29,6 +79,13 @@ Namespace Global.Microsoft.VisualBasic
         [Archive] = 32
     End Enum
 
+    Public Enum FirstWeekOfYear
+        System = 0
+        Jan1 = 1
+        FirstFourDays = 2
+        FirstFullWeek = 3
+    End Enum
+
     <Flags()> Public Enum VbStrConv
         [None] = 0
         [Uppercase] = 1
@@ -51,6 +108,24 @@ Namespace Global.Microsoft.VisualBasic
         [UseDefault] = -2
     End Enum
 
+    Public Enum DateInterval
+        [Year] = 0
+        [Quarter] = 1
+        [Month] = 2
+        [DayOfYear] = 3
+        [Day] = 4
+        [WeekOfYear] = 5
+        [Weekday] = 6
+        [Hour] = 7
+        [Minute] = 8
+        [Second] = 9
+    End Enum
+
+    Public Enum DueDate
+        EndOfPeriod = 0
+        BegOfPeriod = 1
+    End Enum
+
     Public Enum OpenMode
         [Input] = 1
         [Output] = 2
@@ -93,4 +168,47 @@ Namespace Global.Microsoft.VisualBasic
         Public Count As Short
     End Structure
 
+    Public Enum MsgBoxResult
+        Ok = 1
+        Cancel = 2
+        Abort = 3
+        Retry = 4
+        Ignore = 5
+        Yes = 6
+        No = 7
+    End Enum
+
+    <Flags()>
+    Public Enum MsgBoxStyle
+        'You may BitOr one value from each group
+        'Button group: Lower 4 bits, &H00F 
+        OkOnly = &H0I
+        OkCancel = &H1I
+        AbortRetryIgnore = &H2I
+        YesNoCancel = &H3I
+        YesNo = &H4I
+        RetryCancel = &H5I
+
+        'Icon Group: Middle 4 bits &H0F0
+        Critical = &H10I     'Same as Windows.Forms.MessageBox.IconError
+        Question = &H20I     'Same As Windows.MessageBox.IconQuestion
+        Exclamation = &H30I  'Same As Windows.MessageBox.IconExclamation
+        Information = &H40I  'Same As Windows.MessageBox.IconInformation
+
+        'Default Group: High 4 bits &HF00
+        DefaultButton1 = 0
+        DefaultButton2 = &H100I
+        DefaultButton3 = &H200I
+        'UNSUPPORTED IN VB7
+        'DefaultButton4 = &H300I
+
+        ApplicationModal = &H0I
+        SystemModal = &H1000I
+
+        MsgBoxHelp = &H4000I
+        MsgBoxRight = &H80000I
+        MsgBoxRtlReading = &H100000I
+        MsgBoxSetForeground = &H10000I
+    End Enum
+
 End Namespace
diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/Helpers/SafeNativeMethods.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/Helpers/SafeNativeMethods.vb
new file mode 100644 (file)
index 0000000..b83487a
--- /dev/null
@@ -0,0 +1,31 @@
+' Licensed to the .NET Foundation under one or more agreements.
+' The .NET Foundation licenses this file to you under the MIT license.
+' See the LICENSE file in the project root for more information.
+
+Imports System.Runtime.InteropServices
+Imports System.Runtime.Versioning
+
+Namespace Microsoft.VisualBasic.CompilerServices
+
+    <System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)>
+    <ComVisible(False)>
+    Friend NotInheritable Class _
+        SafeNativeMethods
+
+        <ResourceExposure(ResourceScope.None)>
+        <PreserveSig()> Friend Declare Sub _
+            GetLocalTime _
+                Lib "kernel32" (ByVal systime As NativeTypes.SystemTime)
+
+        '''*************************************************************************
+        ''' ;New
+        ''' <summary>
+        ''' FxCop violation: Avoid uninstantiated internal class. 
+        ''' Adding a private constructor to prevent the compiler from generating a default constructor.
+        ''' </summary>
+        Private Sub New()
+        End Sub
+    End Class
+
+End Namespace
+
index 1cc307a..fea3048 100644 (file)
@@ -44,6 +44,10 @@ Namespace Microsoft.VisualBasic.CompilerServices
             ByVal vt As Int16)
         End Sub
 
+        <DllImport("kernel32", PreserveSig:=True, CharSet:=CharSet.Unicode, EntryPoint:="SetLocalTime", SetLastError:=True)>
+        Friend Shared Function SetLocalTime(ByVal systime As NativeTypes.SystemTime) As Integer
+        End Function
+
         <DllImport("kernel32", PreserveSig:=True, CharSet:=CharSet.Auto, EntryPoint:="MoveFile", BestFitMapping:=False, ThrowOnUnmappableChar:=True, SetLastError:=True)>
         Friend Shared Function MoveFile(<[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpExistingFileName As String,
                 <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpNewFileName As String) As Integer
diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/VariantType.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/VariantType.vb
deleted file mode 100644 (file)
index 8ae955c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-' Licensed to the .NET Foundation under one or more agreements.
-' The .NET Foundation licenses this file to you under the MIT license.
-' See the LICENSE file in the project root for more information.
-
-Namespace Microsoft.VisualBasic
-    Public Enum VariantType
-        Empty = 0
-        Null = 1
-        [Short] = 2
-        [Integer] = 3
-        [Single] = 4
-        [Double] = 5
-        Currency = 6
-        [Date] = 7
-        [String] = 8
-        [Object] = 9
-        [Error] = 10
-        [Boolean] = 11
-        [Variant] = 12
-        [DataObject] = 13
-        [Decimal] = 14
-        [Byte] = 17
-        [Char] = 18
-        [Long] = 20
-        UserDefinedType = 36
-        Array = 8192
-    End Enum
-End Namespace
index 6c75dbc..e1a522f 100644 (file)
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Collections.Generic;
+using System.Globalization;
 using Xunit;
 
 namespace Microsoft.VisualBasic.Tests
 {
     public class DateAndTimeTests
     {
+        [Theory]
+        [MemberData(nameof(DateAdd_DateInterval_TestData))]
+        public void DateAdd(DateInterval interval, double number, DateTime dateValue, DateTime expected)
+        {
+            Assert.Equal(expected, DateAndTime.DateAdd(interval, number, dateValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(DateAdd_DateInterval_ArgumentOutOfRangeException_TestData))]
+        public void DateAdd_ArgumentOutOfRangeException(DateInterval interval, double number, DateTime dateValue)
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(() => DateAndTime.DateAdd(interval, number, dateValue));
+        }
+
+        private static IEnumerable<object[]> DateAdd_DateInterval_TestData()
+        {
+            var now = DateTime.UtcNow;
+            var calendar = System.Threading.Thread.CurrentThread.CurrentCulture.Calendar;
+
+            yield return new object[] { DateInterval.Year, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Year, 0.0, now, now };
+            yield return new object[] { DateInterval.Year, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Year, 2.0, DateTime.MinValue, calendar.AddYears(DateTime.MinValue, 2) };
+            yield return new object[] { DateInterval.Year, 2.0, now, calendar.AddYears(now, 2) };
+            yield return new object[] { DateInterval.Year, -2.0, now, calendar.AddYears(now, -2) };
+            yield return new object[] { DateInterval.Year, -2.0, DateTime.MaxValue, calendar.AddYears(DateTime.MaxValue, -2) };
+
+            yield return new object[] { DateInterval.Quarter, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Quarter, 0.0, now, now };
+            yield return new object[] { DateInterval.Quarter, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Quarter, 2.0, DateTime.MinValue, calendar.AddMonths(DateTime.MinValue, 6) };
+            yield return new object[] { DateInterval.Quarter, 2.0, now, calendar.AddMonths(now, 6) };
+            yield return new object[] { DateInterval.Quarter, -2.0, now, calendar.AddMonths(now, -6) };
+            yield return new object[] { DateInterval.Quarter, -2.0, DateTime.MaxValue, calendar.AddMonths(DateTime.MaxValue, -6) };
+
+            yield return new object[] { DateInterval.Month, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Month, 0.0, now, now };
+            yield return new object[] { DateInterval.Month, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Month, 2.0, DateTime.MinValue, calendar.AddMonths(DateTime.MinValue, 2) };
+            yield return new object[] { DateInterval.Month, 2.0, now, calendar.AddMonths(now, 2) };
+            yield return new object[] { DateInterval.Month, -2.0, now, calendar.AddMonths(now, -2) };
+            yield return new object[] { DateInterval.Month, -2.0, DateTime.MaxValue, calendar.AddMonths(DateTime.MaxValue, -2) };
+
+            yield return new object[] { DateInterval.DayOfYear, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.DayOfYear, 0.0, now, now };
+            yield return new object[] { DateInterval.DayOfYear, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.DayOfYear, 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(2) };
+            yield return new object[] { DateInterval.DayOfYear, 2.0, now, now.AddDays(2) };
+            yield return new object[] { DateInterval.DayOfYear, -2.0, now, now.AddDays(-2) };
+            yield return new object[] { DateInterval.DayOfYear, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-2) };
+
+            yield return new object[] { DateInterval.Day, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Day, 0.0, now, now };
+            yield return new object[] { DateInterval.Day, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Day, 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(2) };
+            yield return new object[] { DateInterval.Day, 2.0, now, now.AddDays(2) };
+            yield return new object[] { DateInterval.Day, -2.0, now, now.AddDays(-2) };
+            yield return new object[] { DateInterval.Day, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-2) };
+
+            yield return new object[] { DateInterval.WeekOfYear, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.WeekOfYear, 0.0, now, now };
+            yield return new object[] { DateInterval.WeekOfYear, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.WeekOfYear, 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(14) };
+            yield return new object[] { DateInterval.WeekOfYear, 2.0, now, now.AddDays(14) };
+            yield return new object[] { DateInterval.WeekOfYear, -2.0, now, now.AddDays(-14) };
+            yield return new object[] { DateInterval.WeekOfYear, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-14) };
+
+            yield return new object[] { DateInterval.Weekday, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Weekday, 0.0, now, now };
+            yield return new object[] { DateInterval.Weekday, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Weekday, 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(2) };
+            yield return new object[] { DateInterval.Weekday, 2.0, now, now.AddDays(2) };
+            yield return new object[] { DateInterval.Weekday, -2.0, now, now.AddDays(-2) };
+            yield return new object[] { DateInterval.Weekday, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-2) };
+
+            yield return new object[] { DateInterval.Hour, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Hour, 0.0, now, now };
+            yield return new object[] { DateInterval.Hour, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Hour, 2.0, DateTime.MinValue, DateTime.MinValue.AddHours(2) };
+            yield return new object[] { DateInterval.Hour, 2.0, now, now.AddHours(2) };
+            yield return new object[] { DateInterval.Hour, -2.0, now, now.AddHours(-2) };
+            yield return new object[] { DateInterval.Hour, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddHours(-2) };
+
+            yield return new object[] { DateInterval.Minute, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Minute, 0.0, now, now };
+            yield return new object[] { DateInterval.Minute, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Minute, 2.0, DateTime.MinValue, DateTime.MinValue.AddMinutes(2) };
+            yield return new object[] { DateInterval.Minute, 2.0, now, now.AddMinutes(2) };
+            yield return new object[] { DateInterval.Minute, -2.0, now, now.AddMinutes(-2) };
+            yield return new object[] { DateInterval.Minute, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddMinutes(-2) };
+
+            yield return new object[] { DateInterval.Second, 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { DateInterval.Second, 0.0, now, now };
+            yield return new object[] { DateInterval.Second, 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Second, 2.0, DateTime.MinValue, DateTime.MinValue.AddSeconds(2) };
+            yield return new object[] { DateInterval.Second, 2.0, now, now.AddSeconds(2) };
+            yield return new object[] { DateInterval.Second, -2.0, now, now.AddSeconds(-2) };
+            yield return new object[] { DateInterval.Second, -2.0, DateTime.MaxValue, DateTime.MaxValue.AddSeconds(-2) };
+        }
+
+        private static IEnumerable<object[]> DateAdd_DateInterval_ArgumentOutOfRangeException_TestData()
+        {
+            yield return new object[] { DateInterval.Year, 2.0, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Year, -2.0, DateTime.MinValue };
+
+            yield return new object[] { DateInterval.Day, 2.0, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Day, -2.0, DateTime.MinValue };
+
+            yield return new object[] { DateInterval.Second, 2.0, DateTime.MaxValue };
+            yield return new object[] { DateInterval.Second, -2.0, DateTime.MinValue };
+        }
+
+        [Theory]
+        [MemberData(nameof(DateAdd_StringInterval_TestData))]
+        public void DateAdd(string interval, double number, object dateValue, DateTime expected)
+        {
+            Assert.Equal(expected, DateAndTime.DateAdd(interval, number, dateValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(DateAdd_StringInterval_ArgumentOutOfRangeException_TestData))]
+        public void DateAdd_ArgumentOutOfRangeException(string interval, double number, object dateValue)
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(() => DateAndTime.DateAdd(interval, number, dateValue));
+        }
+
+        private static IEnumerable<object[]> DateAdd_StringInterval_TestData()
+        {
+            var now = DateTime.UtcNow;
+            var calendar = System.Threading.Thread.CurrentThread.CurrentCulture.Calendar;
+
+            yield return new object[] { "YYYY", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "YYYY", 0.0, now, now };
+            yield return new object[] { "YYYY", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "YYYY", 2.0, DateTime.MinValue, calendar.AddYears(DateTime.MinValue, 2) };
+            yield return new object[] { "YYYY", 2.0, now, calendar.AddYears(now, 2) };
+            yield return new object[] { "YYYY", -2.0, now, calendar.AddYears(now, -2) };
+            yield return new object[] { "YYYY", -2.0, DateTime.MaxValue, calendar.AddYears(DateTime.MaxValue, -2) };
+
+            yield return new object[] { "Q", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "Q", 0.0, now, now };
+            yield return new object[] { "Q", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "Q", 2.0, DateTime.MinValue, calendar.AddMonths(DateTime.MinValue, 6) };
+            yield return new object[] { "Q", 2.0, now, calendar.AddMonths(now, 6) };
+            yield return new object[] { "Q", -2.0, now, calendar.AddMonths(now, -6) };
+            yield return new object[] { "Q", -2.0, DateTime.MaxValue, calendar.AddMonths(DateTime.MaxValue, -6) };
+
+            yield return new object[] { "M", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "M", 0.0, now, now };
+            yield return new object[] { "M", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "M", 2.0, DateTime.MinValue, calendar.AddMonths(DateTime.MinValue, 2) };
+            yield return new object[] { "M", 2.0, now, calendar.AddMonths(now, 2) };
+            yield return new object[] { "M", -2.0, now, calendar.AddMonths(now, -2) };
+            yield return new object[] { "M", -2.0, DateTime.MaxValue, calendar.AddMonths(DateTime.MaxValue, -2) };
+
+            yield return new object[] { "Y", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "Y", 0.0, now, now };
+            yield return new object[] { "Y", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "Y", 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(2) };
+            yield return new object[] { "Y", 2.0, now, now.AddDays(2) };
+            yield return new object[] { "Y", -2.0, now, now.AddDays(-2) };
+            yield return new object[] { "Y", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-2) };
+
+            yield return new object[] { "D", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "D", 0.0, now, now };
+            yield return new object[] { "D", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "D", 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(2) };
+            yield return new object[] { "D", 2.0, now, now.AddDays(2) };
+            yield return new object[] { "D", -2.0, now, now.AddDays(-2) };
+            yield return new object[] { "D", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-2) };
+
+            yield return new object[] { "WW", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "WW", 0.0, now, now };
+            yield return new object[] { "WW", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "WW", 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(14) };
+            yield return new object[] { "WW", 2.0, now, now.AddDays(14) };
+            yield return new object[] { "WW", -2.0, now, now.AddDays(-14) };
+            yield return new object[] { "WW", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-14) };
+
+            yield return new object[] { "W", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "W", 0.0, now, now };
+            yield return new object[] { "W", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "W", 2.0, DateTime.MinValue, DateTime.MinValue.AddDays(2) };
+            yield return new object[] { "W", 2.0, now, now.AddDays(2) };
+            yield return new object[] { "W", -2.0, now, now.AddDays(-2) };
+            yield return new object[] { "W", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddDays(-2) };
+
+            yield return new object[] { "H", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "H", 0.0, now, now };
+            yield return new object[] { "H", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "H", 2.0, DateTime.MinValue, DateTime.MinValue.AddHours(2) };
+            yield return new object[] { "H", 2.0, now, now.AddHours(2) };
+            yield return new object[] { "H", -2.0, now, now.AddHours(-2) };
+            yield return new object[] { "H", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddHours(-2) };
+
+            yield return new object[] { "N", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "N", 0.0, now, now };
+            yield return new object[] { "N", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "N", 2.0, DateTime.MinValue, DateTime.MinValue.AddMinutes(2) };
+            yield return new object[] { "N", 2.0, now, now.AddMinutes(2) };
+            yield return new object[] { "N", -2.0, now, now.AddMinutes(-2) };
+            yield return new object[] { "N", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddMinutes(-2) };
+
+            yield return new object[] { "S", 0.0, DateTime.MinValue, DateTime.MinValue };
+            yield return new object[] { "S", 0.0, now, now };
+            yield return new object[] { "S", 0.0, DateTime.MaxValue, DateTime.MaxValue };
+            yield return new object[] { "S", 2.0, DateTime.MinValue, DateTime.MinValue.AddSeconds(2) };
+            yield return new object[] { "S", 2.0, now, now.AddSeconds(2) };
+            yield return new object[] { "S", -2.0, now, now.AddSeconds(-2) };
+            yield return new object[] { "S", -2.0, DateTime.MaxValue, DateTime.MaxValue.AddSeconds(-2) };
+        }
+
+        private static IEnumerable<object[]> DateAdd_StringInterval_ArgumentOutOfRangeException_TestData()
+        {
+            yield return new object[] { "YYYY", 2.0, DateTime.MaxValue };
+            yield return new object[] { "YYYY", -2.0, DateTime.MinValue };
+
+            yield return new object[] { "D", 2.0, DateTime.MaxValue };
+            yield return new object[] { "D", -2.0, DateTime.MinValue };
+
+            yield return new object[] { "S", 2.0, DateTime.MaxValue };
+            yield return new object[] { "S", -2.0, DateTime.MinValue };
+        }
+
+        [Theory]
+        [MemberData(nameof(DateDiff_DateInterval_TestData))]
+        public void DateDiff(DateInterval interval, DateTime dateTime1, DateTime dateTime2, long expected)
+        {
+            Assert.Equal(expected, DateAndTime.DateDiff(interval, dateTime1, dateTime2));
+        }
+
+        private static IEnumerable<object[]> DateDiff_DateInterval_TestData()
+        {
+            var now = DateTime.UtcNow;
+
+            yield return new object[] { DateInterval.Year, DateTime.MinValue, DateTime.MinValue, 0 };
+            yield return new object[] { DateInterval.Year, now, now, 0 };
+            yield return new object[] { DateInterval.Year, DateTime.MaxValue, DateTime.MaxValue, 0 };
+
+            yield return new object[] { DateInterval.Quarter, now, now, 0 };
+
+            yield return new object[] { DateInterval.Month, now, now, 0 };
+
+            yield return new object[] { DateInterval.DayOfYear, now, now, 0 };
+            yield return new object[] { DateInterval.DayOfYear, now, now.AddDays(2), 2 };
+            yield return new object[] { DateInterval.DayOfYear, now, now.AddDays(-2), -2 };
+
+            yield return new object[] { DateInterval.Day, now, now, 0 };
+            yield return new object[] { DateInterval.Day, now, now.AddDays(2), 2 };
+            yield return new object[] { DateInterval.Day, now, now.AddDays(-2), -2 };
+
+            yield return new object[] { DateInterval.Hour, now, now, 0 };
+            yield return new object[] { DateInterval.Hour, now, now.AddHours(2), 2 };
+            yield return new object[] { DateInterval.Hour, now, now.AddHours(-2), -2 };
+
+            yield return new object[] { DateInterval.Minute, now, now, 0 };
+            yield return new object[] { DateInterval.Minute, now, now.AddMinutes(2), 2 };
+            yield return new object[] { DateInterval.Minute, now, now.AddMinutes(-2), -2 };
+
+            yield return new object[] { DateInterval.Second, now, now, 0 };
+            yield return new object[] { DateInterval.Second, now, now.AddSeconds(2), 2 };
+            yield return new object[] { DateInterval.Second, now, now.AddSeconds(-2), -2 };
+        }
+
+        [Theory]
+        [MemberData(nameof(DateDiff_StringInterval_TestData))]
+        public void DateDiff(string interval, object dateTime1, object dateTime2, long expected)
+        {
+            Assert.Equal(expected, DateAndTime.DateDiff(interval, dateTime1, dateTime2));
+        }
+
+        private static IEnumerable<object[]> DateDiff_StringInterval_TestData()
+        {
+            var now = DateTime.UtcNow;
+
+            yield return new object[] { "YYYY", DateTime.MinValue, DateTime.MinValue, 0 };
+            yield return new object[] { "YYYY", now, now, 0 };
+            yield return new object[] { "YYYY", DateTime.MaxValue, DateTime.MaxValue, 0 };
+
+            yield return new object[] { "Q", now, now, 0 };
+
+            yield return new object[] { "M", now, now, 0 };
+
+            yield return new object[] { "Y", now, now, 0 };
+            yield return new object[] { "Y", now, now.AddDays(2), 2 };
+            yield return new object[] { "Y", now, now.AddDays(-2), -2 };
+
+            yield return new object[] { "D", now, now, 0 };
+            yield return new object[] { "D", now, now.AddDays(2), 2 };
+            yield return new object[] { "D", now, now.AddDays(-2), -2 };
+
+            yield return new object[] { "H", now, now, 0 };
+            yield return new object[] { "H", now, now.AddHours(2), 2 };
+            yield return new object[] { "H", now, now.AddHours(-2), -2 };
+
+            yield return new object[] { "N", now, now, 0 };
+            yield return new object[] { "N", now, now.AddMinutes(2), 2 };
+            yield return new object[] { "N", now, now.AddMinutes(-2), -2 };
+
+            yield return new object[] { "S", now, now, 0 };
+            yield return new object[] { "S", now, now.AddSeconds(2), 2 };
+            yield return new object[] { "S", now, now.AddSeconds(-2), -2 };
+        }
+
+        [Theory]
+        [MemberData(nameof(DatePart_DateInterval_TestData))]
+        public void DatePart(DateInterval interval, DateTime dateValue, int expected)
+        {
+            Assert.Equal(expected, DateAndTime.DatePart(interval, dateValue));
+        }
+
+        private static IEnumerable<object[]> DatePart_DateInterval_TestData()
+        {
+            var now = DateTime.UtcNow;
+            var calendar = System.Threading.Thread.CurrentThread.CurrentCulture.Calendar;
+
+            yield return new object[] { DateInterval.Year, now, calendar.GetYear(now) };
+            yield return new object[] { DateInterval.Month, now, calendar.GetMonth(now) };
+            yield return new object[] { DateInterval.Day, now, calendar.GetDayOfMonth(now) };
+            yield return new object[] { DateInterval.Hour, now, calendar.GetHour(now) };
+            yield return new object[] { DateInterval.Minute, now, calendar.GetMinute(now) };
+            yield return new object[] { DateInterval.Second, now, calendar.GetSecond(now) };
+        }
+
+        [Theory]
+        [MemberData(nameof(DatePart_StringInterval_TestData))]
+        public void DatePart(string interval, object dateValue, int expected)
+        {
+            Assert.Equal(expected, DateAndTime.DatePart(interval, dateValue));
+        }
+
+        private static IEnumerable<object[]> DatePart_StringInterval_TestData()
+        {
+            var now = DateTime.UtcNow;
+            var calendar = System.Threading.Thread.CurrentThread.CurrentCulture.Calendar;
+
+            yield return new object[] { "YYYY", now, calendar.GetYear(now) };
+            yield return new object[] { "M", now, calendar.GetMonth(now) };
+            yield return new object[] { "D", now, calendar.GetDayOfMonth(now) };
+            yield return new object[] { "H", now, calendar.GetHour(now) };
+            yield return new object[] { "N", now, calendar.GetMinute(now) };
+            yield return new object[] { "S", now, calendar.GetSecond(now) };
+        }
+
+        // Not tested:
+        //   public static DateTime DateSerial(int Year, int Month, int Day) { throw null; }
+
+        [Fact]
+        public void DateString()
+        {
+            string str = DateAndTime.DateString;
+            // Should return a date with three non-empty parts.
+            string[] parts = str.Split('-');
+            Assert.Equal(3, parts.Length);
+            foreach (var part in parts)
+            {
+                Assert.False(string.IsNullOrEmpty(part));
+            }
+        }
+
+        // Not tested:
+        //   public static string DateString { set { } }
+        //   public static DateTime DateValue(string StringDate) { throw null; }
+
         [Fact]
-        public void Now_ReturnsDateTimeNow()
+        public void Fields()
+        {
+            var now = DateTime.UtcNow;
+            var calendar = System.Threading.Thread.CurrentThread.CurrentCulture.Calendar;
+
+            Assert.Equal(calendar.GetYear(now), DateAndTime.Year(now));
+            Assert.Equal(calendar.GetMonth(now), DateAndTime.Month(now));
+            Assert.Equal(calendar.GetDayOfMonth(now), DateAndTime.Day(now));
+            Assert.Equal(calendar.GetHour(now), DateAndTime.Hour(now));
+            Assert.Equal(calendar.GetMinute(now), DateAndTime.Minute(now));
+            Assert.Equal(calendar.GetSecond(now), DateAndTime.Second(now));
+        }
+
+        [Fact]
+        public void MonthName()
+        {
+            var culture = System.Threading.Thread.CurrentThread.CurrentCulture;
+            try
+            {
+                System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
+
+                Assert.Throws<ArgumentException>(() => DateAndTime.MonthName(0, Abbreviate: false));
+                Assert.Throws<ArgumentException>(() => DateAndTime.MonthName(0, Abbreviate: true));
+
+                Assert.Equal("January", DateAndTime.MonthName(1, Abbreviate: false));
+                Assert.Equal("Jan", DateAndTime.MonthName(1, Abbreviate: true));
+
+                Assert.Equal("December", DateAndTime.MonthName(12, Abbreviate: false));
+                Assert.Equal("Dec", DateAndTime.MonthName(12, Abbreviate: true));
+
+                Assert.Throws<ArgumentException>(() => DateAndTime.MonthName(int.MaxValue, Abbreviate: false));
+                Assert.Throws<ArgumentException>(() => DateAndTime.MonthName(int.MaxValue, Abbreviate: true));
+            }
+            finally
+            {
+                System.Threading.Thread.CurrentThread.CurrentCulture = culture;
+            }
+        }
+
+        [Fact]
+        public void Now()
         {
             var dateTimeNowBefore = DateTime.Now;
             var now = DateAndTime.Now;
@@ -19,8 +425,15 @@ namespace Microsoft.VisualBasic.Tests
             Assert.InRange(now, dateTimeNowBefore, dateTimeNowAfter);
         }
 
+        // Not tested:
+        //   public static DateTime TimeOfDay { get { throw null; } set { } }
+        //   public static double Timer { get { throw null; } }
+        //   public static DateTime TimeSerial(int Hour, int Minute, int Second) { throw null; }
+        //   public static string TimeString { get { throw null; } set { } }
+        //   public static DateTime TimeValue(string StringTime) { throw null; }
+
         [Fact]
-        public void Today_ReturnsDateTimeToday()
+        public void Today()
         {
             var dateTimeTodayBefore = DateTime.Today;
             var today = DateAndTime.Today;
@@ -29,5 +442,35 @@ namespace Microsoft.VisualBasic.Tests
             Assert.InRange(today, dateTimeTodayBefore, dateTimeTodayAfter);
             Assert.Equal(TimeSpan.Zero, today.TimeOfDay);
         }
+
+        // Not tested:
+        //   public static DateTime Today { set { } }
+        //   public static int Weekday(System.DateTime DateValue, FirstDayOfWeek DayOfWeek = FirstDayOfWeek.Sunday) { throw null; }
+
+        [Fact]
+        public void WeekdayName()
+        {
+            var culture = System.Threading.Thread.CurrentThread.CurrentCulture;
+            try
+            {
+                System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
+
+                Assert.Throws<ArgumentException>(() => DateAndTime.WeekdayName(0, Abbreviate: false));
+                Assert.Throws<ArgumentException>(() => DateAndTime.WeekdayName(0, Abbreviate: true));
+
+                Assert.Equal("Sunday", DateAndTime.WeekdayName(1, Abbreviate: false));
+                Assert.Equal("Sun", DateAndTime.WeekdayName(1, Abbreviate: true));
+
+                Assert.Equal("Saturday", DateAndTime.WeekdayName(7, Abbreviate: false));
+                Assert.Equal("Sat", DateAndTime.WeekdayName(7, Abbreviate: true));
+
+                Assert.Throws<ArgumentException>(() => DateAndTime.WeekdayName(int.MaxValue, Abbreviate: false));
+                Assert.Throws<ArgumentException>(() => DateAndTime.WeekdayName(int.MaxValue, Abbreviate: true));
+            }
+            finally
+            {
+                System.Threading.Thread.CurrentThread.CurrentCulture = culture;
+            }
+        }
     }
 }