Ruby ouput(string and integers) - ruby

I have to output(string & integers) something like this on the same line: Sat, 7 May 2016 15:27:40 -0400
This is what I'm running to output.
print "\tCreated On: "+(package["created"] == nil ? "" : package["created"]).to_s + "\n";
But my output is returning like this.
Created On: 1462649260418

You can do something like this:
print "\tCreated On: #{Time.at(package['created'].to_i / 1000).strftime('%d/%b/%Y') unless package["created"].nil?}\n"

If all you have is a timestamp you need to convert it to a time. That looks like a millisecond epoch timestamp, so you can convert it with:
Time.at(package['created'] / 1000)
Then use strftime to format as required.

Related

Procmail filtering by Date: field

I need to move away mails older than given time - let it be 24h = 86400s. I use old good procmail for multiple other purposes on that machine, so I wanted to use is as well for this purpose. It also behaves well under the load (~1 000 000 small automated messages per day).
It took me a while to get to this ugly solution (excerpt from bigger procmailrc file):
Grab Date: field using formail
Grab current date in UNIX format (seconds)
bash convert the mail date to unix format
compare values using bash
return result to procmail using exit code.
Together:
MAILDATE_RFC=`formail -zxDate:`
DATE_UNIX=`date "+%s"`
:0
* ? MAILDATE_UNIX=`date -d "$MAILDATE_RFC" "+%s"` ; if ( (( ($DATE_UNIX-$MAILDATE_UNIX) > 86400)) ) then exit 0; else exit 1; fi
! account_for_outdated_mails
In this case I need to use the "Date:" field, as this contains the local time at which the mail was generated (it can take multiple days to get to my machine). We are 100% sure that "Date:" field exists and contains RFC-style date (those are automated messages in separated mail network).
My solution looks pretty ugly:
Getting the comparison result from bash using exit codes looks pretty bad. Might be inefficient as well.
I would like to calculate the MAILDATE_RFC still in procmail but it seems I cannot use any variable as the argument to generate another variable:
MAILDATE_UNIX=`date -d "$MAILDATE_RFC" "+%s"`
does not work.
The only optimization I am aware of would be to push the whole process of getting MAILDATE_RFC, MAILDATE_UNIX and DATE_UNIX processed in bash script and doing it in one bash session instead of 3.
My question: Is there a better way to do it? Maybe more efficient?
What you say doesn't work actually does. Here's a quick demo.
testing.rc:
DEFAULT=/dev/null
SHELL=/bin/sh
VERBOSE=yes
MAILDATE_RFC=`formail -zxDate:`
MAILDATE_UNIX=`date -d "$MAILDATE_RFC" "+%s"`
NOW=`date +%s`
:0
* 86400^0 ^
* $ -$NOW^0 ^
* $ $MAILDATE_UNIX^0 ^
{ LOG="score: $=
" }
Test run, in a fresh Ubuntu 20.04 Docker image:
tripleee#bash$ procmail -m testing.rc <<\:
> Subject: demo message
> Date: Fri, 10 Jun 2022 06:20:36 +0000
>
> Try me
> :
procmail: [263] Fri Jun 10 06:21:23 2022
procmail: Executing "formail,-zxDate:"
procmail: [263] Fri Jun 10 06:21:23 2022
procmail: Assigning "MAILDATE_RFC=Fri, 10 Jun 2022 06:20:36 +0000"
procmail: Executing "date,-d,Fri, 10 Jun 2022 06:20:36 +0000,+%s"
procmail: Assigning "MAILDATE_UNIX=1654842036"
procmail: Executing "date,+%s"
procmail: Assigning "NOW=1654842083"
procmail: Score: 86400 86400 "^"
procmail: Score: -1654842083 -1654755683 "^"
procmail: Score: 1654842036 86353 "^"
procmail: Assigning "LOG=score: 86353
"
score: 86353
procmail: Assigning "LASTFOLDER=/dev/null"
procmail: Opening "/dev/null"
Folder: /dev/null 68
This also demonstrates how to use scoring to do the calculation. It's perhaps somewhat intimidating, but saves an external process, and so should be more efficient than doing the calculation in Bash.
In some more detail, 123^0 regex says to add 123 to the score just once if the message matches the regex regex (in the recipe above, we use the regex ^ which of course always matches; every message contains a beginning. You could change the 0 to e.g. 1 to say to add for every match, or etc - see the procmailsc man page for proper documentation). The $ modifier says to expand any variables in the recipe itself.
If you are not using GNU date, you don't have date -d; in that case, probably refer to your platform's man page for how to calculate a date stamp for an arbitrary date. How to convert date string to epoch timestamp with the OS X BSD `date` command? has a discussion for MacOS, which should also work for any other *BSD platform.
If you really wanted to make this more efficient, and can be sure that the Date: header really always uses the RFC-mandated format, you could even parse the date in Procmail. Something like
:0
* ^Date: [A-Z][a-z][a-z], \/[ 0-9][0-9] [A-Z][a-z][a-z] [0-9][0-9][0-9][0-9]
{
date=$MATCH
:0
* date ?? ^\/[ 0-9][0-9]
{ dd=$MATCH }
:0
* date ?? ^[ 0-9][0-9] \/[A-Z][a-z][a-z]
{ mon=$MATCH }
* date ?? [A-Z][a-z][a-z] \/[0-9][0-9][0-9][0-9]
{ yyyy=$MATCH }
:0
* mon ?? 1^0 ^Jan
* mon ?? 2^0 ^Feb
* mon ?? 3^0 ^Mar
* mon ?? 4^0 ^Apr
* mon ?? 5^0 ^May
* mon ?? 6^0 ^Jun
* mon ?? 7^0 ^Jul
* mon ?? 8^0 ^Aug
* mon ?? 9^0 ^Sep
* mon ?? 10^0 ^Oct
* mon ?? 11^0 ^Nov
* mon ?? 12^0 ^Dec
{ mm=$= }
}
The \/ token in a regex says to save the matched text after it into the special variable MATCH. We then copy that variable to date and perform additional matching to extract its parts.
Performing the necessary arithmetic to convert this into seconds since January 1, 1970 should be doable at this point, I hope. If you need complete per-day accuracy, you would also need to extract the time and the time zone and adjust to the correct day if it's not in your preferred time zone, or perhaps UTC (that would be +0000 at the very end); but this is just a sketch, anyway, because I think I have a better idea altogether.
Namely, save the messages to the correct folder as they arrive, then just forward or discard or archive older folders when you no longer need them.
MAILDATE_RFC=`formail -czxDate:`
MAILDATE=`date -d "$MAILDATE_RFC" +%F`
:0:
inbox-$MAILDATE
This will save to an mbox file named like inbox-2022-06-10 based on the extracted Date: header. (Again, you could avoid the external processes if you really wanted to squeeze out the last bit of performance, using the date parsing sketch above. And again, if you can't have a message from a different time zone land in the previous or next day's folder, you need to recalculate the date for your time zone.)

MetaTrader 4 / MQL4 Time is off by -5 hours but only when using epoc time

I'm working with MetaTrader4 running in WINE in Ubuntu 16.04. I have a simple inline function that saves the time and various other info to a file using this line:
FileWrite(data_filehandle, "sys_time:" + (string)TimeLocal() + "." + StringFormat("%06lu", usec_instance) + ", sym:" + (string)Symbol() + ", tick_time:" + (string)last_tick.time + ", ask:" + (string)last_tick.ask + ", bid:" + (string)last_tick.bid);
Using the directive:
#property strict
will cause it to output the time in a Date Time format.
Removing that directive will cause it to output time in epoc format.
When it uses Date Time format ( by using '#property strict' ), the time is correct.
It outputs:
sys_time:2020.01.21 07:38:02.994394, sym:EURUSD, tick_time:2020.01.21 14:38:03, ask:1.1104, bid:1.1103
This matches my system time correctly.
Now if I remove '#property strict' to switch to epoc time
It outputs:
sys_time:1579592538.630395, sym:EURUSD, tick_time:1579617738, ask:1.1105, bid:1.11041
my local time is:
$ date '+%s'
1579610544
$ date '+%Z %z'
EST -0500
my time: 1579610544 - MT4 LocalTime: 1579592538 = 18006 seconds (Which is 5 hours and 6 sec behind me)
Any idea on what could be causing this?
I might be slightly less confused if it were +5 hours because that would be GMT.
But it's -5 hours which is Hawaii.
Also... why is the time correct in one format, but not in the other format?
Additional info
I ran some more tests using additional MQL4 functions. I had them constantly pump out their results to my text file. I then quickly whipped together a BASH script to check out the results. I found the following:
Using this code in MT4
FileWrite(data_filehandle, "TimeDaylightSavings(): " + (string)TimeDaylightSavings());
FileWrite(data_filehandle,"TimeLocal(): "+(string)TimeLocal());
FileWrite(data_filehandle,"TimeGMTOffset(): "+(string)TimeGMTOffset());
FileWrite(data_filehandle,"TimeGMT(): "+(string)TimeGMT()+"\n\n");
Gave this output to my text file ( one fresh record about every second ):
TimeDaylightSavings(): 0
TimeLocal(): 1579601184
TimeGMTOffset(): 18000
TimeGMT(): 1579619184
I whipped up this BASH script to scan and check the results in real time:
#!/bin/bash
IFS=$'\n'$'\b';
while true
do
my_time=$(date);
my_epoc=$(date '+%s');
my_record="$( cat EURUSD_price_data.txt| dos2unix | tail -5 )";
mt4_time_local=$( echo "$my_record" | grep -w 'TimeLocal' );
echo "Reading line: $mt4_time_local";
mt4_time_local=$(echo $mt4_time_local | awk '{print $2}' );
echo "My time: $my_time -- My epoc: $my_epoc -- MT4_TimeLocal epoc: $mt4_time_local -- Difference: $(( $my_epoc - $mt4_time_local ))";
mt4_time_GMT=$( echo "$my_record" | grep -w 'TimeGMT' );
echo "Reading line: $mt4_time_GMT";
mt4_time_GMT=$(echo $mt4_time_GMT | awk '{print $2}' );
echo "My time: $my_time -- My epoc: $my_epoc -- MT4_TimeGMT epoc: $mt4_time_GMT -- Difference: $(( $my_epoc - $mt4_time_GMT ))";
echo "";
sleep 1;
done
and got this result:
Reading line: TimeLocal(): 1579601184
My time: Tue Jan 21 10:06:25 EST 2020 -- My epoc: 1579619185 -- MT4_TimeLocal epoc: 1579601184 -- Difference: 18001
Reading line: TimeGMT(): 1579619184
My time: Tue Jan 21 10:06:25 EST 2020 -- My epoc: 1579619185 -- MT4_TimeGMT epoc: 1579619184 -- Difference: 1
Now if I add '#property strict' to switch back to Date Time format I get:
TimeDaylightSavings(): 0
TimeLocal(): 2020.01.21 10:23:56
TimeGMTOffset(): 18000
TimeGMT(): 2020.01.21 15:23:56
My system time:
$ date
Tue Jan 21 10:23:57 EST 2020
Conclusion
For some reason when getting epoc time TimeLocal() gives the wrong time (Hawaiian time for some reason ) , but surprisingly TimeGMT() gives the correct time, even though I am in the EST timezone.
Using the exact same code and set up, when getting the time in Date Time format ( using the '#property strict' directive ) the situation is reversed. TimeLocal() gives the correct time and TimeGMT() gives the wrong time ( but at least it gives correct GMT time )
Is this a bug in MT4, or is there something going on behind the scenes that I haven't fully understood yet?
Q : Any idea on what could be causing this?
The #property strict is a compiler-phase kill-switch, which changes lots of details how the MQL4, syntactically correct, compositions will get understood in either { "old" | "new" }-fashion
( not reading this part of the documentation each time after MT4 IDE update may and will surprise you, so better re-read it always after each and every update )
"Old"-MQL4 used a int32 for datetime internal storage, "New"-MQL4.56789… uses int64, so any roll-overs are way farther.
FileWrite( data_filehandle, "sys_time:"
+ (string)TimeLocal() // localhost-dependent
+ "."
+ StringFormat( "%06lu", usec_instance )
+ ", sym:"
+ (string)Symbol()
+ ", tick_time:"
+ (string)last_tick.time // Fx-QUOTE-dependent
+ ", ask:"
+ (string)last_tick.ask
+ ", bid:"
+ (string)last_tick.bid
);
See TimeGMT() and TimeGMTOffset() for other built-in options.
After a lot of reading, thinking and testing I have found the answer ( though I don't know what they were thinking when they did things this way ).
The issue is right here:
TimeDaylightSavings(): 0
TimeLocal(): 1579601184 <-- should be the same as TimeGMT(). Epoc does not respect timezone
TimeGMTOffset(): 18000
TimeGMT(): 1579619184
Unix epoc time is based on an event that happened on Jan 1st 1970 00:00 UTC.
It does not respect time zones. It is supposed to be the same for everyone on Earth at all times.
You can also see from the original problem that anytime I use the:
date '+%s'
command that my system gives me a correct Unix epoc which matches the output of TimeGMT() from MT4. So the problem is not my system.
However, above we can see that TimeLocal() is not treating the epoc the way that it should. It is adjusting the unix epoc in an attempt to compensate for my time zone. This behavior is probably how it accomplishes producing the correct time when it is displayed in Date Time format. The problem is that when it is asked to produce the time in epoc format it is still doing time zone conversions, which violates that very meaning of Unix epoc time.
So, the solution ( as far as I can tell ) is to simply use TimeGMT() anytime I want a correct Unix epoc. It seems pretty crazy that I have to specifically avoid using TimeLocal() in certain cases... but I guess that's just the way it is?

Changing the time format in Ruby application

My current date format is 19:35, but I want it to display as this format: 2013-07-29 7:13 UTC.
How can I do this? My current code is now = Time.now.gmtime.strftime("%H:%M").
Have you tried
Time.now.utc
?
That prints the current time in UTC format.
now = Time.now.gmtime.strftime("%Y-%m-%d %l:%M %Z")
That should do the trick
http://www.ruby-doc.org/stdlib-2.0/libdoc/date/rdoc/DateTime.html#method-i-strftime

How do I output to the following format: month - year?

Today's month is November (11). With 1.years.ago.to_date..Date.today how can I output:
11 - 2010, 12 - 2010, 01 - 2011, 02 - 2011, 03 - 2011, etc
strftime
Use function for all date modifications in ruby
Refer This DOC
There's probably a more efficient way to do this, but this will give you the output you want:
require "active_support/core_ext/integer/time"
((1.year.ago.to_date)..(Date.today)).map { |d| d.strftime("%m-%Y") }.uniq!
For print date used strtotime() function.
//For today print a date used the following code
echo date('m/d/Y',strtotime("today"));
//For one year ago print a date used the following code
echo date('m.d.Y',strtotime("-1 years"));
//For coming year date from today used following code
echo date('m.d.Y',strtotime("1 years"));
You can to add a new format to your locales.
#/config/locales/en.yml
en:
date:
formats:
month_year: "%m - %Y"
and to use it with I18n.l(your_date, :format => :month_year)
This will help if you want to change the format later, you will change in a unique point.

ROR + Ruby Date From XML API

By using XML API, I got date-time as "2008-02-05T12:50:00Z". Now I wanna convert this text format into different format like "2008-02-05 12:50:00". But I am getting proper way.
I have tried this one :: #a = "2008-02-05T12:50:00Z"
Steps
1. #a.to_date
=> Tue, 05 Feb 2008
2. #a.to_date.strftime('%Y')
=> "2008"
3. #a.to_date.strftime('%Y-%m-%d %H:%M:%S')
=> "2008-02-05 00:00:00
Suggest some thing ?
The to_date method converts your string to a date but dates don't have hours, minutes, or seconds. You want to use DateTime:
require 'date'
d = DateTime.parse('2008-02-05T12:50:00Z')
d.strftime('%Y-%m-%d %H:%M:%S')
# 2008-02-05 12:50:00
Use Ruby's DateTime:
DateTime.parse("2008-02-05T12:50:00Z") #=> #<DateTime: 2008-02-05T12:50:00+00:00 (353448293/144,0/1,2299161)>
From there you can output the value in any format you want using strftime. See Time#strftime for more info.

Resources