Linux date command adds 10 hours to every datetime automatically - date

If I enter date +"%Y/%m/%d %H:%M" -d "20200819T1234" the expected output is 2020/08/19 12:34 when in I actually get 2020/08/19 02:34 that is, exactly 10 hours less. Could someone explain to me why this happens?
At the moment I manage with + 10 hours at the end of the command, but I don't think this is normal. The time zone set on the server is -03 so I am very confused.
This happens in both Ubuntu 16 and Debian 10

The GNU code for parsing dates (parse_datetime2) has this table embedded within it that provides the reason why you're getting the incorrect time (trimmed for conciseness):
/* Military time zone table.
Note 'T' is a special case, as it is used as the separator in ISO
8601 date and time of day representation. */
static table const military_table[] =
{
{ "A", tZONE, -HOUR ( 1) },
{ "B", tZONE, -HOUR ( 2) },
{ "C", tZONE, -HOUR ( 3) },
: : :
{ "Y", tZONE, HOUR (12) },
{ "Z", tZONE, HOUR ( 0) },
{ NULL, 0, 0 }
};
And, indeed, if you run date in debug mode, you can see what's happening (output trimmed for conciseness):
pax> for i in {A..I} {K..Z} ; do
...> date -d $i --debug 2>&1 | awk -vZ=$i '/parsed zone/{print " "Z":"$5}'
...> done
A:UTC-01
B:UTC-02
: :
T:UTC+07
: :
Z:UTC+00
Most letters apply a timezone offset based on military timezones, hence the T that would normally be used to separate date and time in ISO format is being handled differently here, as specifying UTC+7, explaining the ten-hour difference between that and your server at UTC-3.
The bottom line is that you need to use an input format that's acceptable to date. That's as simple as (in this case) replacing the T with a space, as per the following transcript:
pax:~> ### First, the problematic one.
pax:~> date +"%Y/%m/%d %H:%M" -d "20200819T1234" --debug
date: parsed number part: (Y-M-D) 2020-08-19
date: parsed zone part: UTC+07
date: parsed number part: 12:34:00
date: input timezone: parsed date/time string (+07)
date: using specified time as starting value: '12:34:00'
date: starting date/time: '(Y-M-D) 2020-08-19 12:34:00 TZ=+07'
date: '(Y-M-D) 2020-08-19 12:34:00 TZ=+07' = 1597815240 epoch-seconds
date: timezone: system default
date: final: 1597815240.000000000 (epoch-seconds)
date: final: (Y-M-D) 2020-08-19 05:34:00 (UTC)
date: final: (Y-M-D) 2020-08-19 13:34:00 (UTC+08)
2020/08/19 13:34
pax:~> ### Then, the correct one.
pax:~> date +"%Y/%m/%d %H:%M" -d "20200819 1234" --debug
date: parsed number part: (Y-M-D) 2020-08-19
date: parsed number part: 12:34:00
date: input timezone: system default
date: using specified time as starting value: '12:34:00'
date: starting date/time: '(Y-M-D) 2020-08-19 12:34:00'
date: '(Y-M-D) 2020-08-19 12:34:00' = 1597811640 epoch-seconds
date: timezone: system default
date: final: 1597811640.000000000 (epoch-seconds)
date: final: (Y-M-D) 2020-08-19 04:34:00 (UTC)
date: final: (Y-M-D) 2020-08-19 12:34:00 (UTC+08)
2020/08/19 12:34

Your format is mismatch with the time string: try
date +"%Y/%m/%d %H:%M" -d "2020/08/19 12:34"
2020/08/19 12:34

Related

How to convert time from Asia/Kolkata Timezone to Asia/Tokyo Timezone, then insert the Asia/Tokyo specific date to MongoDB

My Date is in the format 2020-07-08 00:00:00 Asia/Kolkata
I want to convert it to 2020-07-08 03:30:00 Asia/Tokyo,
Then insert this date 2020-07-08 03:30:00 as ISO date to MongoDB.
I tried, with ISODate function, which takes DateFormat and Timezone, but it created the date 5 H 30 M ahead of this time, which should be 3 H 30 M ahead.
As Tokyo time is 3 H 30 M ahead of India time.
You can use $dateFromParts to manipulate ISODate to any required format.
Check if the below query helps you out
db.test4.aggregate([
{$project:{
"original": "$date",
"convertedDate": {
'$dateFromParts': {
'year': {$year:{date:'$date'}},
'month': {$month:{date:'$date'}},
'day': {$dayOfMonth:{date:'$date'}},
'hour': {$hour:{date:'$date'}},
'minute': {$minute:{date:'$date'}},
'second': {$second:{date:'$date'}},
'millisecond': {$millisecond:{date:'$date'}},
'timezone': '-0330',
}
}
}}
])

How can compare Date on mongo without time?

This is a sample data
[{ date: '2020-05-21T14:02:00.0123 }, { date: '2020-05-22T14:02:00.0123 }, { date: '2020-05-23T14:02:00.0123 }]
I want to filter records of 22-May or earlier, here is my expected:
[{ date: '2020-05-21T14:02:00.0123 }, { date: '2020-05-22T14:02:00.0123 }]
I tried with this query:
{ date: { $lte: new Date('2020-05-22') }}
But it returns only data earlier 22-May. I think problem is { date: { $lte: new Date('2020-05-22') }} will data.date lte 2020-05-22T00:00:00.000
How I can exclude time ?
You need to match type of input with type of date field in document, either both should be Date's or strings. I would highly suggest maintain dates as dates in DB. Also you need to know that dates in MongoDB are of format ISODate() and holds UTC date.
If your DB date field is of type date :
I want to filter records of 22-May or earlier
As you wanted to get documents <= 22-May, then sending new Date('2020-05-22') doesn't work. Cause :
when you do new Date('2020-05-22'), it will give you Fri May 22 2020 00:00:00 GMT only if you belong to UTC, for example if you're in New York America which is 4 hours behind UTC then it would result in Thu May 21 2020 20:00:00 GMT-0400 (Eastern Daylight Time) which represents EDT, basically it's your system/app server time i.e; local date time.
So if your region is behind UTC then you'll get a back date Thu May 21 2020 otherwise if it's ahead of UTC then there is no issue you'll see Fri May 22 2020.
Ok, now that we've fixed date issues, but we need to look into hours now :
Since you want docs <= 22-May then Fri May 22 2020 00:00:00 GMT doesn't work you need to have either <= Fri May 22 2020 23:59:59 GMT or Sat May 23 2020 00:00:00 GMT. In order to get that :
let date = new Date('2020-05-22')
date.setDate(date.getUTCDate()); // Setting utc date, Only useful if you're region is behind UTC
date = new Date(date.setHours(23,59,59,999)) // This overrides hours generated with 23:59:59 - which is what exactly needed here.
/** Now do your query */
{ date: { $lte: date }}
If your DB date field is of type string :
Then you don't need to convert string to date, instead you can send input date in string format :
let date = new Date('2020-05-22').toISOString() // 2020-05-22T00:00:00.000Z
/** Above would get you an ISO string no matter which region you're in, 
* now since we need `2020-05-22T23:59:59.000Z` which is not easy on ISO string
* We would just do +1 on date like `new Date('2020-05-23').toISOString()` - // 2020-05-23T00:00:00.000Z */
let date = new Date('2020-05-23').toISOString(); // like this
date = date.slice(0, -1) // removing `Z` from date string as your `date` field doesn't have this.
// Now your query is just `$lt`
{ date: { $lt: date }}
Test : mongoplayground

unix date command with nanosecond precision. Input parameter

I'm having difficulty parsing an inputted date with nanosecond precision:
date: invalid date `15-OCT-18 12:40:01:000203570 AM'
Yet when I drop the nanoseconds, it works fine:
$ date -d "15-OCT-18 12:40:01 AM" +"%d-%m-%Y %H:%M:%S %p"
15-10-2018 00:40:01 AM
Looking the docs its suggests uppercase N is to be used for ns
Even when I drop the Ns it generates the ns for me
$ date -d "15-OCT-18 12:40:01 AM" +"%d-%m-%Y %H:%M:%S:%N %p"
15-10-2018 00:40:01:000000000 AM
Should be in the format
date -d "15-OCT-18 12:40:01.000203570 AM" +"%d-%m-%Y %H:%M:%S:%N %p"
Data needs to have . instead of : spearating seconds and ns
You need to replace the : before the Nanoseconds identifier with .(dot)
> date -d"$(echo "15-OCT-18 12:40:01:000203570 AM" | sed 's/:/./3')" +"%d-%m-%Y %H:%M:%S.%N %p"
15-10-2018 00:40:01.000203570 AM
>

Golang - Date Parsing a YYYY-MM-DD date

Hi so I can't seem to find anything to help me on this.
I am using the format string
"January 02, 2006"
and the time string
"2016-07-08"
However when I run a format using these parameters the response I get is July 7th, 2016. The correct response would be July 8th, 2016.
As a note, I am also trying to use this via Sprig.
{{ date "January 02, 2006" .MyDate }}
If I can get any assistance it would be much appreciated
It's because of the time zone, you're getting the right date, but sprig formats to "Local" by default, where golang.org/pkg/time defaults to "UTC"
Here is a sample code: (omitting error handling for simplicity)
func main() {
// using the "time" package
mydate, _ := time.Parse("2006-01-02", "2016-07-08")
fmt.Println("time:", mydate.In(time.Local).Format("January 02, 2006 (MST)"), "-- specify Local time zone")
fmt.Println("time:", mydate.Format("January 02, 2006 (MST)"), "-- defaults to UTC")
d := struct{ MyDate time.Time }{mydate}
//using sprig
fmap := sprig.TxtFuncMap()
localTpl := `sprig: {{ date "January 02, 2006 (MST)" .MyDate }} -- defaults to Local`
t := template.Must(template.New("test").Funcs(fmap).Parse(localTpl))
var localdate bytes.Buffer
t.Execute(&localdate, d)
fmt.Println(localdate.String())
utcTpl := `sprig: {{ dateInZone "January 02, 2006 (MST)" .MyDate "UTC"}} -- specify UTC time zone`
t = template.Must(template.New("test").Funcs(fmap).Parse(utcTpl))
var utcdate bytes.Buffer
t.Execute(&utcdate, d)
fmt.Println(utcdate.String())
}
Output:
time: July 07, 2016 (EDT) -- specify Local time zone
time: July 08, 2016 (UTC) -- defaults to UTC
sprig: July 07, 2016 (EDT) -- defaults to Local
sprig: July 08, 2016 (UTC) -- specify UTC time zone
Here is some reference:
time: https://golang.org/pkg/time
In the absence of a time zone indicator, Parse returns a time in UTC.
spig: https://github.com/Masterminds/sprig/blob/master/functions.go#L407
func date(fmt string, date interface{}) string {
return dateInZone(fmt, date, "Local")
}
Note: if you want to format to a specific time zone, look at the 2nd template:
utcTpl := `sprig: {{ dateInZone "January 02, 2006 (MST)" .MyDate "UTC"}} -- specify UTC time zone`
I think the correct way is to send time.Time type to your template and then use Format function on it. You can use ParseTime to parse your 2016-07-08 format.
type Data struct {
CreatedOn time.Time
}
template.Execute(w, Data{})
Template:
<span>{{ .CreatedOn.Format "January 02, 2006" }}</span>

Zend_Date: wrong results on DST change day

"25 Mar 2012" was the date when time was changed from 02:00am to 03:00am in the Czech Republic. On that date, one functionality on my website stopped working correctly and a customer complained, etc. After digging for a few hours, I figured out that on that day Zend_Date behaved strangely:
#!/usr/bin/env php
<?php
include 'Zend/Date.php';
date_default_timezone_set('Europe/Prague');
shell_exec('sudo date --set="25 Mar 2012 12:00:00"');
$date = new Zend_Date();
$date->set('00:01:00', Zend_Date::TIMES);
$startDate = $date->get(Zend_Date::TIMESTAMP);
echo 'start date: ' . date("j.n.Y H:i", $startDate) . PHP_EOL;
$date->set('23:59:00', Zend_Date::TIMES);
$endDate = $date->get(Zend_Date::TIMESTAMP);
echo 'end date: ' . date("j.n.Y H:i", $endDate) . PHP_EOL;
This outputs:
start date: 24.3.2012 23:01
end date: 24.3.2012 23:59
which is off by day.
If I change the date to "26 Mar 2012 12:00:00", it correctly outputs:
start date: 26.3.2012 00:01
end date: 26.3.2012 23:59
Using mktime instead of Zend_Date works correctly in both cases. Is it bug in Zend_Date? I think it is, so I have already posted a bug report http://framework.zend.com/issues/browse/ZF-12121. But maybe I am missing something obvious?
I've just find this on stack overflow, it perfectly fixed my issue (same as yours)
See Bug in Zend_Date (back in time)
Good luck
When testing the code with just hardcoding the date: $date = new Zend_Date('2012-03-25 4:00:00', 'YYYY-MM-dd H:mm:ss'); the result is ok. Try to see whether the date output is the same when using $date->toString('d.M.yyyy HH:mm');