Strange Date object in MongoDB [duplicate] - mongodb

As per MDN
"Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC."
Then why does it accept negative values ?
Even if it did shouldn't negative value mean values before Jan 1, 1970 ?
new Date('0000', '00', '-1'); // "1899-12-30T05:00:00.000Z"
new Date('0000', '00', '00'); // "1899-12-31T05:00:00.000Z"
new Date('-9999', '99', '99'); // "-009991-07-08T04:00:00.000Z"
What is happening ?
Update
For some positive values , the year begins from 1900
new Date(100); // "1970-01-01T00:00:00.100Z" // it says 100Z
new Date(0100); // "1970-01-01T00:00:00.064Z" // it says 64Z
new Date("0006","06","06"); // "1906-07-06T04:00:00.000Z"
Also note that, in the last one, the date is shown as 4 which is wrong.
I suspect this is some sort of Y2K bug ?!!

This is hard and inconsistent, yes. The JavaScript Date object was based on the one in Java 1.0, which is so bad that Java redesigned a whole new package.
JavaScript is not so lucky.
Date is "based on" unix epoch because of how it is defined. It's internal details.
1st Jan 1970 is the actual time of this baseline.
since is the direction of the timestamp value: forward for +ve, backward for -ve.
Externally, the Date constructor has several different usages, based on parameters:
Zero parameters = current time
new Date() // Current datetime. Every tutorial should teach this.
The time is absolute, but 'displayed' timezone may be UTC or local.
For simplicity, this answer will use only UTC. Keep timezone in mind when you test.
One numeric parameter = timestamp # 1970
new Date(0) // 0ms from 1970-01-01T00:00:00Z.
new Date(100) // 100ms from 1970 baseline.
new Date(-10) // -10ms from 1970 baseline.
One string parameter = iso date string
new Date('000') // Short years are invalid, need at least four digits.
new Date('0000') // 0000-01-01. Valid because there are four digits.
new Date('1900') // 1900-01-01.
new Date('1900-01-01') // Same as above.
new Date('1900-01-01T00:00:00') // Same as above.
new Date('-000001') // 2 BC, see below. Yes you need all those zeros.
Two or more parameters = year, month, and so on # 1900 or 0000
new Date(0,0) // 1900-01-01T00:00:00Z.
new Date(0,0,1) // Same as above. Date is 1 based.
new Date(0,0,0) // 1 day before 1900 = 1899-12-31.
new Date(0,-1) // 1 month before 1900 = 1899-12-01.
new Date(0,-1,0) // 1 month and 1 day before 1900 = 1899-11-30.
new Date(0,-1,-1) // 1 month and *2* days before 1900 = 1899-11-29.
new Date('0','1') // 1900-02-01. Two+ params always cast to year and month.
new Date(100,0) // 0100-01-01. Year > 99 use year 0 not 1900.
new Date(1900,0) // 1900-01-01. Same as new Date(0,0). So intuitive!
Negative year = BC
new Date(-1,0) // 1 year before 0000-01-01 = 1 year before 1 BC = 2 BC.
new Date(-1,0,-1) // 2 days before 2 BC. Fun, yes? I'll leave this as an exercise.
There is no 0 AC. There is 1 AC and the year before it is 1 BC. Year 0 is 1 BC by convention.
2 BC is displayed as year "-000001".
The extra zeros are required because it is outside normal range (0000 to 9999).
If you new Date(12345,0) you will get "+012345-01-01", too.
Of course, the Gregorian calendar, adopted as late as 1923 in Europe, will cease to be meaningful long before we reach BC.
In fact, scholars accept that Jesus wasn't born in 1 BC.
But with the stars and the land moving at this scale, calendar is the least of your worries.
The remaining given code are just variations of these cases. For example:
new Date(0100) // One number = epoch. 0100 (octal) = 64ms since 1970
new Date('0100') // One string = iso = 0100-01-01.
new Date(-9999, 99, 99) // 9999 years before BC 1 and then add 99 months and 98 days
Hope you had some fun time. Please don't forget to vote up. :)
To stay sane, keep all dates in ISO 8601 and use the string constructor.
And if you need to handle timezone, keep all datetimes in UTC.

Well, firstly, you're passing in string instead of an integer, so that might have something to do with your issues here.
Check this out, it explains negative dates quite nicely, and there is an explanation for your exact example.

Then why does it accept negative values ?
You are confusing the description of how the data is stored internally with the arguments that the constructor function takes.
Even if it did shouldn't negative value mean values before Jan 1, 1970 ?
No, for the above reason. Nothing stops the year, month or day from being negative. You just end up adding a negative number to something.
Also note that, in the last one, the date is shown as 4 which is wrong.
Numbers which start with a 0 are expressed in octal, not decimal. 0100 === 64.

Please have a look at the documentation
Year: Values from 0 to 99 map to the years 1900 to 1999
1970 with appropriate timezone: new Date(0); // int MS since 1970
1900 (or 1899 with applied timezone): new Date(0,0) or new Date(0,0,1) - date is 1 based, month and year are 0 based
1899: new Date(0,0,-1)

Related

CDO - Resample netcdf files from monthly to daily timesteps

I have a netcdf file that has monthly global data from 1991 to 2000 (10 years).
Using CDO, how can I modify the netcdf from monthly to daily timesteps by repeating the monthly values each day of each month?
for eaxample,
convert from
Month 1, value = 0.25
to
Day 1, value = 0.25
Day 2, value = 0.25
Day 3, value = 0.25
....
Day 31, value = 0.25
convert from
Month 2, value = 0.87
to
Day 1, value = 0.87
Day 2, value = 0.87
Day 3, value = 0.87
....
Day 28, value = 0.87
Thanks
##############
Update
my monthly netcdf has the monthly values not on the first day of each month, but in sparse order. e.g. on the 15th, 7th, 9th, etc.. however one value for each month.
The question is perhaps ambiguously worded. Adrian Tompkins' answer is correct for interpolation. However, you are actually asking to set the value for each day of the month to that for the first day of the month. You could do this by adding a second CDO call as follows:
cdo -inttime,1991-01-01,00:00:00,1day in.nc temp.nc
cdo -monadd -gtc,100000000000000000 temp.nc in.nc out.nc
Just set the value after gtc to something much higher than anything in your data.
You can use inttime which interpolates in time at the interval required, but this is not exactly what you asked for as it doesn't repeat the monthly values and your series will be smoothed by the interpolation.
If we assume your dataset starts on the 1st January at time 00:00 (you don't state in the question) then the command would be
cdo inttime,1991-01-01,00:00:00,1day in.nc out.nc
This performs a simple linear interpolation between steps.
Note: This is fine for fields like temperature and seems to be want you ask for, but readers should note that one has to be more careful with flux fields such as rainfall, where one might want to scale and/or change the units appropriately.
I could not find a solution with CDO but I solved the issue with R, as follows:
library(dplyr)
library(ncdf4)
library(reshape2)
## Read ncfile
ncpath="~/my/path/"
ncname="my_monthly_ncfile"
ncfname=paste(ncpath, ncname, ".nc", sep="")
ncin=nc_open(ncfname)
var=ncvar_get(ncin, "nc_var")
## melt ncfile
var=melt(var)
var=var[complete.cases(var), ] ## remove any NA
## split ncfile by gridpoint (lat and lon) into a list
var=split(var, list(var$lat, var$lon))
var=var[lapply(var,nrow)>0] ## remove any empty list element
## create new list and replicate, for each gridpoint, each monthly value n=30 times
var_rep=list()
for (i in 1:length(var)) {
var_rep[[i]]=data.frame(value=rep(var[[i]]$value, each=30))
}

Extract time from date time and find difference between 2 times

I am trying to convert EPOC time to date time and need to extract the time only from that
I am doing below
$min = $Time_Start | measure -Minimum
$max = $Time_End | measure -Maximum
[datetime]$oUNIXDatemin=(Get-Date 01.01.1970)+([System.TimeSpan]::fromseconds($min.Minimum))
$oUNIXDatemin_1 = $oUNIXDatemin.ToString("HH:mm:ss")
[datetime]$oUNIXDatemax=(Get-Date 01.01.1970)+([System.TimeSpan]::fromseconds($max.Maximum))
$oUNIXDatemax_1 = $oUNIXDatemax.ToString("HH:mm:ss")
Problem is while converting I am getting $oUNIXDatemin_1 and $oUNIXDatemax_1 value like
$oUNIXDatemin_1
12 October 2021 07:46:46
$oUNIXDatemax_1
12 October 2021 21:16:04
My EPOC values are
$min.Minimum
1634024806
$max.Maximum
1634073364
Please let me know what is wrong here. Need to find the difference in HH:mm:ss format.
In PowerShell, you'd usually use a format string. Subtracting two PowerShell datetimes returns a value of type Timespan, which is well-behaved over a span of more than 24 hours.
([datetime]"12 October 2021 21:16:04" - [datetime]"12 October 2021 07:46:46") -f "HH:mm:ss"
13:29:18
Be careful here. Both intervals (durations) and time (of day) have the same format, but different meanings. For example, it makes sense to multiply the interval "01:00:00" (1 hour) by 3 to get three hours; it doesn't make sense to multiply the time "01:00:00" (1 o'clock AM) by 3.
I'm sure the overall calculation can be simplified, but it's too early for me.

nvd3 (d3.js) date format returns incorrect month

My data looks like this:
[{ x="2013-06-01", y=3}, { x="2013-07-01", y=7 }, { x="2013-08-01", y=3 }]
Chart x-axis is formatted as so:
chart.xAxis
.axisLabel('Date')
.tickFormat(function(d) { return d3.time.format('%b %Y')(new Date(d)); })
;
%b returns May, Jun, July respectively for the dates 2013-06-01, 2013-07-01, 2013-08-01
Why is it returning the previous month, and how can I fix it?
EDIT: If the date is formatted as 2013-06-02, it will return the correct month... does someone know what is happening to cause this?
#Amelia is correct it's because of timezone difference and because Date defaults to 24:00:00 if you don't specify a time. So, in case of EDT, which is -4:00, you lose 4 hours which puts you in the previous day (May 31 2013 20:00:00) and because the days in your dates are 01, this puts you in the previous month.
To bypass this you could append a time to your date if that is allowable in your case.
chart.xAxis
.axisLabel('Date')
.tickFormat(function(d) {
d = d.split('-')
// Create new date by using new Date(year, month, day, hour, second, ms)
// Subtracting 1 is necessary since Javascript months are 0 - 11.
return d3.time.format('%b %Y')(new Date(d[0], +d[1] - 1, d[2], 12, 0, 0));
});
Here is a working Fiddle

UTC Time to String Conversion

I am looking for helping doing time conversions from UTC time to string using MATLAB.
I am trying to extract time from a data file collected at the end of October 2010.
The data file says it is reporting in UTC time and the field is an integer string value in milliseconds that is around 3.02e11. I would like to convert this to a string but am have some trouble.
I figured out that the units are most definitely in milliseconds so I convert this to fractions of days to be compatible with datenum format.
If the data was collected at the end of October (say, October 31, 2010) then I can guess what kind of number I might get. I thought that January 1, 2001 would be a good epoch and calculated what sort of number (in days) I might get:
suspectedDate = datenum('October 31, 2010')
suspectedEpoch = datenum('January 1, 2001')
suspectedTimeInDays = suspectedDate - suspectedEpoch
Which comes out as 3590.
However, my actual time, in days, comes out with the following code
actualTime = 3.02e11
actualTimeInDays = 3.02e11/1000/24/3600
as 3495.4.
This is troubling as the difference is only 94.6 -- not a full year. This would mean either the documentation for the file is wrong or the epoch is close to April 1-5, 2001:
calculatedEpoch = suspectedDate - actualTimeInDays
calculatedEpochStr = datestr(calculatedEpoch)
Alternately, if the epoch is January 1, 2001 then the actual date in the file is from the end of July.
ifEpochIsJanuaryDate = suspectedEpoch + actualTimeInDays
ifEpochIsJanuaryDateStr = datestr(ifEpochIsJanuaryDate)
Is this a known UTC format and can anyone give suggestions on how to get an October date from 3.02e11 magnitude number?
Unix time today is about 13e11, and is measured in ms since 1970.
If your time is ~3e11, then it's probably since year 2000.
>> time_unix = 1339116554872; % example time
>> time_reference = datenum('1970', 'yyyy');
>> time_matlab = time_reference + time_unix / 8.64e7;
>> time_matlab_string = datestr(time_matlab, 'yyyymmdd HH:MM:SS.FFF')
time_matlab_string =
20120608 00:49:14.872
Notes:
1) change 1970 into 2000 if your time is since 2000;
2) See the definition of matlab's time.
3) 8.64e7 is number of milliseconds in a day.
4) Matlab does not apply any time-zone shifts, so the result is the same UTC time.
5) Example for backward transformation:
>> matlab_time = now;
>> unix_time = round(8.64e7 * (matlab_time - datenum('1970', 'yyyy')))
unix_time =
1339118367664
You can't just make up your own epoch. Also datenum returns things in days. So the closeness you got with doing your math was just a coincidence.
Turns out that
>> datenum('Jan-1-0000')
ans =
1
and
>> datenum('Jan-1-0001')
ans =
367
So Matlab should be returning things in days since Jan. 1, 0000. (Not a typo)
However, I'd look carefully at this 3.02e11 number and find out exactly what it means. I'm pretty sure it's not standard Unix UTC, which should be seconds since January 1, 1970. It's way too big. It's close to GMT: Mon, 1 Jan 11540 08:53:20 UTC.

Cocoa Touch: Laying out dates on a month-view calendar

I'm aware that there are several Cocoa Touch/iPhone calendar implementations available online, but for certain reasons I'm trying to create my own. I'm running into an issue where the code that I use to lay out the dates (which I represent as instances of UIView placed as subviews into another UIView) is messing up in December.
Currently, what I do is decompose the date into an instance of NSDateComponents, then get the week and weekday properties of the components to figure out the X and Y "positions" of the date view, respectively. I can offset the X position by the week property for the first day of the month I'm laying out.
Brief example: the first day of August 2009 falls on a Saturday, and its date components' week property is 31 (using a Gregorian calendar). Therefore its Y position is 6 and its X position is 0, and the X offset I'll be using is 31. So I can take the second day of August, which is a Sunday, and determine that its X position is 0 and its Y position is week - 31 = 32 - 31 = 1. This way I can lay out a zero-indexed grid of date views for the month of August, and it all goes swimmingly...
...until I try to do the same for December. In December of 2009, apparently the week property wraps to 1 on the 27th (a Sunday), meaning that I wind up trying to place the 27th through the 31st at Y positions -48 or so.
My question is twofold: why does the week property wrap partway into the last month of the year? Is it indexed at the last Sunday of the previous year, rather than the first day of the year? And second, is there a better way to lay out a date grid like this (using other components from an NSDateComponents instance, or anything else I can get from an NSDate and an NSCalendar), or do I just have to add a check for the "last week of year" condition?
The last few days in December start to belong to week 1 of the next year. (see here)
Instead of using the week property to calculate the weekday positions, I'd just start with Y=0 and then increase it after each Saturday (if your week starts on Sundays)
int x = <calculate x based on the weekday of the 1st of the month>
int y = 0
for (days in month) {
<add subview for this day>
x += xOffset
if (currentWeekday == saturday) {
x = 0
y += yOffset
}
}
P.S.: I'd probably look at the current locale to determine the first weekday:
NSLocale *locale = [NSLocale currentLocale];
NSCalendar *calendar = [locale objectForKey:NSLocaleCalendar];
NSUInteger firstWeekday = [calendar firstWeekday];
I probably wouldn't use weeks in my calculation. You need to lay out the days in rows of 7, which of course we know conceptually as weeks. Practically you should be able to get away just knowing the day of the year and doing a modulus.
Say the year starts on Sunday (column 1) and you want know the position of the 100th day. Well 100 / 7 = 14 with a remainder. So it is in the 14th row. Then do a mod 100 % 7 = 2. So it falls on a Monday (in my example).