Dateadd error when subtracting from 0:00 - vba

I am trying to convert column with GMT hour to the specified time zones from the user.
I get an error when VBA attempts to subtract 18000 secs (GMT-5) from 01:00.
Selected_GMT = -18000
CellValue = "1/0/00 01:00"
New_Time = DateAdd("s", Selected_GMT,CellValue)
Is this error happening because VBA is unable to determine the hours before 00:00?
I have figured out the seconds for Selected_GMT, how can I use that to determine New_Time?

As ooo noted in a comment above, 1/0/00 is an invalid date code. However even if that was a typo in your question, the fact that the date uses a 2 digit year code begs the question "WHICH year 00?" Apologies if you already know this, but below I've extracted a recap of how Excel dates work from something that I've written elsewhere. The relevant part is "Day Zero And Before In Excel"; if the "00" actually represents *19*00 in the cell (as it will if you've just punched in "01:00 as the cell entry), you're going to run into problems subtracting from that. In which case, perhaps explicitly enter the date and time (perhaps using the current date) but hide the date component using formatting):
Excel uses a "date serial" system in which any date that you use in
calculations is represented as a positive integer value. That integer
value is calculated from an arbitrary starting date. Adding whole
numbers to a specific serial date moves you forward through the
calendar a day at a time, and subtracting whole numbers moves you
backwards... as long as you don't go past the starting date of the
serial number system and end up with a negative value. Times are
represented as fractions of a day; 0.25 for 6am, 0.5 for noon, 0.75
for 6pm and so on.
Excel Dates
In the case of Excel for Windows, the starting date is 1 January 1900. That is, if you enter the value 1 into a cell in Excel
and format it as a date, you'll see the value as 1 January 1900. 2
will be the 2nd of January 1900, 3 the 3rd of January, and so on. 367
represents 1 January 1901 because Excel treats 1900 as having been a
leap year with 366 days. In other words, every full day that passes
adds 1 to the serial date.
It's important to remember that the above relates to Excel only, and
not to Access, SQL Server or other database products (or Visual Basic,
for that matter). In Access, for example, the range of valid dates is
1 January 100 to 31 December 9999, the same range that can be stored
in a VB or VBA variable with a Date data type.
Excel And The Macintosh
Macintosh systems use a start date of 1 January 1904, neatly bypassing the 1900 leap year issue. However that
does mean that there's a 4 year discrepancy between the serial date
values in a workbook created in Excel for Windows, and one created in
Excel for the Mac. Fortunately under Tools -> Options-> Calculation
(on pre-2007 versions of Excel) you'll find a workbook option called
1904 Date System. If that's checked, Excel knows that the workbook
came from a Macintosh and will adjust its date calculations
accordingly.
Excel Times
As noted in the introduction, times are calculated as a
fraction of a day. For example 1.5 represents noon on 2 January 1900.
1.75 represents 6pm on 2 January 1900.
(Snipped a bit about the leap year bug in 1900)
From 1 March 1900 onward Excel's dates are correct, but if you format
the number 1 using the format dddd, mmmm dd, yyyy you'll get the
result Sunday, 1 January 1900. That is incorrect; 1 January 1900 was a
Monday, not a Sunday. This day of week error continues until you reach
1 March, which is the first truly correct date in the Excel calendar.
Day Zero And Before In Excel
If you use the value zero and display it
in date format you'll get the nonsense date Saturday 0 January 1900.
If you try to format a negative value as a date, you'll just get a
cell full of hash marks. Similarly if you try to obtain a date serial
number using Excel functions like DateValue, you can only do so for
dates on or after 1 January 1900. An attempt to specify an earlier
date will result in an error.
The 1904 (Macintosh) system starts from zero. (1 January 1904 has a
value of 0, not 1. Excel's on-line help describes the Mac system as
starting from January 2, but that's probably easier than explaining to
users why a serial date value of 0 works on the Mac but not Excel.)
Negative numbers won't generate an error, but the number will be
treated as absolute. That is, both 1 and -1 will be treated as 2
January 1904.

Related

Date Error when running a SQL Query in Excel

When running a SQL query in an Excel macro enabled workbook it displays the date value wrong in excel but shows the correct date in the Power Query Editor. I have created the same query in a new workbook and I don't get the same error? It is off by 1461 days. Any suggestions?
Snapshot of Issue
Microsoft Excel supports two different date systems. These systems are the 1900 date system and the 1904 date system.
In the 1900 date system, the first day that is supported is January 1, 1900.
In the 1904 date system, the first day that is supported is January 1, 1904.
See https://support.microsoft.com/en-us/help/214330/differences-between-the-1900-and-the-1904-date-system-in-excel and https://support.office.com/en-us/article/date-systems-in-excel-e7fe7167-48a9-4b96-bb53-5612a800b487
The difference between the two date systems is 1,462 days; that is, the serial number of a date in the 1900 Date System is always 1,462 days bigger than the serial number of the same date in the 1904 date system. And this is exactly the difference between the dates in Excel sheet and Power Query showed in your picture.
The Excel sheet you are showing runs in the 1904 date system while your Power Query Editor uses 1900 date system.
Example: 11/8/2017 has serial number 43047 in 1900 date system. The same serial number in 1904 date system points to 1462 days later which is 11/9/2021.
The linked articles also show how to change the date system for the workbook.

xlwings - early dates (<=1900's)

Note:
xw.__version__
Out[84]: '0.10.2'
pd.__version__
Out[85]: '0.16.2'
I have the following df:
>>> df.head()
data
1900-01-31 0.0315
1900-02-28 0.0314583333333
1900-03-31 0.0314166666667
1900-04-30 0.031375
1900-05-31 0.0313333333333
and when I run:
xw.sheets(str(sht)).range(k).value = d_of_dfs[k]
I see the following in excel:
data
1900-02-01 0.0315
1900-02-29 0.031458333
1900-03-31 0.031416667
1900-04-30 0.031375
1900-05-31 0.031333333
1900-06-30 0.031291667
1900-07-31 0.03125
1900-08-31 0.031208333
1900-09-30 0.031166667
1900-10-31 0.031125
is xlwings hijacking the early date and messing it up?
Also - xlwings cannot handle dates prior to 1900 at all.
This issue stems from the way excel stores dates and a bug that harkens back to Lotus 123.
From http://www.cpearson.com/excel/datetime.htm
Dates
The integer portion of the number, ddddd, represents the number of
days since 1900-Jan-0. For example, the date 19-Jan-2000 is stored as
36,544, since 36,544 days have passed since 1900-Jan-0. The number 1
represents 1900-Jan-1. It should be noted that the number 0 does not
represent 1899-Dec-31. It does not. If you use the MONTH function
with the date 0, it will return January, not December. Moreover, the
YEAR function will return 1900, not 1899.
Actually, this number is one greater than the actual number of days.
This is because Excel behaves as if the date 1900-Feb-29 existed. It
did not. The year 1900 was not a leap year (the year 2000 is a leap
year). In Excel, the day after 1900-Feb-28 is 1900-Feb-29. In
reality, the day after 1900-Feb-28 was 1900-Mar-1 . This is not a
"bug". Indeed, it is by design. Excel works this way because it was
truly a bug in Lotus 123. When Excel was introduced, 123 has nearly
the entire market for spreadsheet software. Microsoft decided to
continue Lotus' bug, in order to fully compatible. Users who switched
from 123 to Excel would not have to make any changes to their data.
As long as all your dates later than 1900-Mar-1, this should be of no
concern.
This answer has more detail though I've just been converting the date to string which excel seems to parse correctly.
converted = str(datetime.date(1900, 1, 1))

Trying to format date to save worksheet

I am looking to save an individual worksheet from a workbook with today's date in the filename. ex. (c:\HotDogS\sales\Daily_12_04_16.xslx)
The problem I am encountering is getting the date to show right in the filename.
I have 1 cell that has the simple formula of =TODAY(). The cell is formatted for mm/dd/yy.
The formula I am trying to use to save the date for the sheet is:
=left(B3,2)&"_"&mid(B3,4,2)&"_"&right(B3,2)
So I am expecting a date of 12/04/16 to come out as 12_04_16, but I am getting is, 42_08_08.
Can somebody shed some light on this??
Thank you!!
Assuming TODAY is 4 December 2016, i.e. serial day number 42708, your formula is:
=left(B3,2)&"_"&mid(B3,4,2)&"_"&right(B3,2)
Left(B3,2) is 42. Mid(B3,4,2) is 08. Right(B3,2) is 08.
So your final result is 42_08_08.
You probably want to use (as an Excel formula):
=TEXT(B3,"mm\_dd\_yy")
Or in VBA you could use
Format(Range("B3").Value, "mm_dd_yy")
Excel stores dates as the number of days (and fractions of a day) since 0 January 1900. Therefore
1 January 1900 is day 1
31 January 1900 is day 31
1 February 1900 is day 32
29 February 1900 (even though it doesn't exist - but the bug has been maintained for backward compatibility) is day 60
1 January 1901 is day 367
4 December 2016 is day 42708
NOW() is day 42709.328 (it's about 7:52am on 5 December 2016 at the moment)
Referencing a cell formatted as date returns the underlying date serial number.
To get a date formatted as you want use
=TEXT(B3,"dd\_mm\_yy")

VB.NET DatetimePicker - Wrong week number

I have an issue with my vbnet extented datetime picker.
When the element pass to new year (2016), the week number displayed on the left is wrong.
I have a "datetimepicker" which is not the default component, it was downloaded here :
http://www.codeproject.com/Articles/17063/ExtendedDateTimePicker-control-with-week-numbers
I don't understand why the calendar pass from 53 to 2 and not 53 to 1.
Maybe one of you has the same error.
Thanks for your time.
I don't understand why the calendar pass from 53 to 2 and not 53 to 1
It is pretty much working as expected. The way it is counting weeks, those first 3 days of 2016 count as the first week of 2016.
Note that the control doesnt do anything calendar or display related. It is simply changing the display style of the calendar window provided by Windows. The code seen on the CP page is all there is and mainly it just sets a style flag to tell Windows to add the week numbers:
style = style | MCS_WEEKNUMBERS;
The MSDN entry for it indicates:
Week 1 is defined as the first week that contains at least four days.
Since Jan 1-3 is not 4 days, it would seem that there is either an error, a different calendar being used or MSDN is out of date.
From comments:
From what i understood, what's wrong is "date format". Maybe it's not a 8601
No, it is more than that: ISO8601 is a different calendar which neither Windows nor NET implements. Wikipedia notes:
The first week of a year is the week that contains the first Thursday of the year (and, hence, always contains 4 January). ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
This is what you see in the calendar drop down.
Alternative
But the ISO8601 Week Of Year is easy to calculate:
Start with the code for GetISOWeekOfYear() from my answer to a very similar question. You can use that to display the ISO8601 week of year for the selected date in a label or something next to the DTP.
Print the first and last week numbers for 2011 To 2021:
Dim cal As Calendar = CultureInfo.CurrentCulture.DateTimeFormat.Calendar
For n As Int32 = 2011 To 2017 '2021
dt = New DateTime(n, 12, 21)
Console.WriteLine(" ***** {0} *****", n)
For j = 0 To 3
Dim NetWk = cal.GetWeekOfYear(dt, CalendarWeekRule.FirstDay, firstD)
Console.WriteLine("Invariant Date: {0} ISO #:{1:00} NET #:{2:00}",
dt.ToString("MM/dd/yyyy"), GetISOWeekOfYear(dt), NetWk)
dt = dt.AddDays(7)
Next
Next
The result for 2015/2016 portion:
***** 2015 *****
Invariant Date: 12/21/2015 ISO #:52 NET #:52
Invariant Date: 12/28/2015 ISO #:53 NET #:53
Invariant Date: 01/04/2016 ISO #:01 NET #:02
Invariant Date: 01/11/2016 ISO #:02 NET #:03
***** 2016 *****
Invariant Date: 12/21/2016 ISO #:51 NET #:52
Invariant Date: 12/28/2016 ISO #:52 NET #:53
Invariant Date: 01/04/2017 ISO #:01 NET #:01
Invariant Date: 01/11/2017 ISO #:02 NET #:02
Unless you are willing to write your own control from scratch or license one which can be set to a different calendar (and has a definition for ISO8601), that may be the best you can do.
The Bottomline: The Week number is not wrong. It using a different calendar than you expect/want.
References:
Get or convert NET GetWeekOfYear() to ISO week
MSDN: Month Calendar Control Styles
DateTimePicker in Reference Source
The control is working fine.
When the year changes over the final few days of the year are in week 53 - but it's not a full week. Similarly the first few days of the year are in week 1, but the control takes the system's "first day of the week" setting to determine when week 2 begins - so it is possible for the first week of the year to have any where from 1 to 7 days in it.
This means that the image you've shown is showing Week 53 because you're in December and Week 2 because the 2nd week of January does start on the 4th.
If you navigate to January it would display week 1 for the row starting on December 28.
The bottom-line is that the first week in January only has 3 days in it.
This is just the normal and correct behaviour of this control.

How to get Month from ISO Date and Week

I'm looking for a way to convert an ISO date to Month and I also need to covert an ISO week to Month.
I need to do this in Excel and Access.
I found this formula for excel but when converting it to Access it does not work. Is there a simple way to accomplish this?
I found this Excel formula to convert ISO date to month (C2=date) and it works perfect:
=MONTH(DATE(YEAR(C2),MONTH(C2)+(WEEKDAY(C2,2)+(DAY(DATE(YEAR(C2),MONTH(C2)+1,0)))-(DAY(C2))<4),(((7-(WEEKDAY(C2,2)))+(DAY(C2)))>3)))
But when I modify it for an Access query it does not return the correct values:
Date_to_Month:MONTH(DATESERIAL(YEAR([WW_Index].[ISO_date]),MONTH([WW_Index].[ISO_date])+(WEEKDAY([WW_Index].[ISO_date],2)+(DAY(DATESERIAL(YEAR([WW_Index].[ISO_date]),MONTH([WW_Index].[ISO_date])+1,0)))-(DAY([WW_Index].[ISO_date]))<4),(((7-(WEEKDAY([WW_Index].[ISO_date],2)))+(DAY([WW_Index].[ISO_date])))>3)))
I also need to convert ISO week_year to Month. I found this formula but it does not work:
=MONTH(DATE(YEAR(C2),1,-2)-WEEKDAY(DATE(YEAR(C2),1,3))+D2*7)
Example: week 18, 2012 is the ISO week of Apr 30 through May 6, 2012. There is less that 4 April days in this week thus week 18, 2012 is in May.
Any help would be greatly appreciated.
I don't know access but you can do the first part (date to month) much more easily in excel with this formula
=MONTH(C2-WEEKDAY(C2-1)+4)
That should be easier to convert for access......
For the second part you are finding the Monday of the relevant week, hence you get the wrong month in some cases, the Thursday of the week (midpoint) should always be within the correct month so you can just add 3 to get that (-2 becomes 1), i.e.
=MONTH(DATE(YEAR(C2),1,1)-WEEKDAY(DATE(YEAR(C2),1,3))+D2*7)
I assume C2 is a date within the relevant year and D2 is the ISO week number
but probably better to have C2 containing the year, e.g. just 2013 and then you can use
=MONTH(DATE(C2,1,1)-WEEKDAY(DATE(C2,1,3))+D2*7)