calculating YearWeek from Tcl - tcl

I'm trying to correctly calculate working Year/Week number from a date field.
I tried to use the clock format command as follows
% clock format [clock scan "2016.01.01" -format "%Y.%m.%d"] -format "%Y-WW%V"
2016-WW53
and while the Week number is correct, the year is not because in this case Jan1 lands in week 53, as it did in 2016. Since the Tcl clock format command specifies the week number and the year separately, I end up with Jan 1, 2016 being shown as 2016-WW53 but this should be shown as 2015-WW53.
Is there a built in function for this or do I need to use an if/then condition to choose the year correctly?

Just use the modifier %G:
clock format [clock scan "2016.01.01" -format "%Y.%m.%d"] -format "%G-WW%V"
Output:
2015-WW53
From the manual:
%G
On output, produces a four-digit year number suitable for use with the week-based ISO8601 calendar; that is, the year number corresponds to the week number produced by %V. On input, accepts such a four-digit year number, possibly with leading whitespace.

Related

How to input year and month?

I'm trying to input date strings comprising a month and year, e.g. January 2000.
According to the man page, %B (and %b) "On input, matches the name of the month in the given locale (in either abbreviated or full form, or any unique prefix of either form)", but I can't make this work:
% clock scan "January 2000" -format "%B %Y"
1475881200
% clock format 1475881200 -format "%B %Y"
October 2016
It looks to me as though Tcl doesn't understand something and is defaulting to today's date.
I'd like my command to return 946684800, the result of [clock scan 2000-01-01 -format %Y-%M-%D]
Is there a problem with [clock scan], the documentation or my reading of the documents?
I can see the same problem, but only if I don't specify the day of the month. If I do, things work:
% clock scan "1 January 2000" -format "%d %B %Y"
946684800
% clock format 946684800
Sat Jan 01 00:00:00 GMT 2000
While yes, I suppose this is a bug (and you probably ought to report it on the core.tcl-lang.org issue tracker), adding in a (fake?) day of the month seems like an easy enough workaround. After all, without it should the parser default to the current day-of-month or the first or some other day? What's the representative day? Specify it and the problem goes away.
Interesting question. It appears you need to also specify a day
$ echo 'puts [clock format [clock scan "January 2000" -format "%B %Y"]]' | tclsh8.6
Sat Oct 08 00:00:00 EDT 2016
$ echo 'puts [clock format [clock scan "1 January 2000" -format "%d %B %Y"]]' | tclsh8.6
Sat Jan 01 00:00:00 EST 2000
I see in the documentation (http://tcl.tk/man/tcl8.6/TclCmd/clock.htm) a section starting with
The date is determined according to the fields that are present in the preprocessed format string. In order of preference:
ending with
If none of the above rules results in a usable date, the date of the base time in the given time zone is used.
It's probably in #3 where you're expecting to match but aren't.

Date validation with the clock command

Consider the following code run on a Windows 7 system:
% info patchlevel
8.6.4
% clock scan "1995-01-35" -format "%Y-%m-%d"
791856000
% clock format [clock scan "1995-01-35" -format "%Y-%m-%d"] -format "%Y-%m-%d"
1995-02-04
%
I ran into this situation when trying to determine if a string was a valid date, I was expecting the first clock scan to fail as 35 isn't a valid day, but what happens is that I get a date 35 days after the 1st of January.
In my code I'm now comparing the output of the 2nd clock command to the original input and deciding that the string isn't really a valid date if the result is different.
Is there a better way to validate a date and is this the expected behaviour of the clock command, I can't find it described in the manual page for clock?
It is not in-built functionality in Tcl. If the dates/months are exceeding, then it is added to the successive days/months.
In your case, you are giving 35th of month January. The additional 4 days (i.e. 31 + 4 = 35) are added and calculated as month February's 4th day.
In the bizarre case that adding the given number of days yields a date
that does not exist because it falls within the dropped days of the
Julian-to-Gregorian conversion, the date is converted as if it was on
the Julian calendar.
Adding a number of months, or a number of years, is similar; it
converts the given time to a calendar date and time of day. It then
adds the requisite number of months or years, and reconverts the
resulting date and time of day to an absolute time.
If the resulting date is impossible because the month has too few days
(for example, when adding 1 month to 31 January), the last day of the
month is substituted. Thus, adding 1 month to 31 January will result
in 28 February in a common year or 29 February in a leap year.
proc is_valid_date {date {date_format "%Y-%m-%d"}} {
return [string equal [clock format [clock scan $date -format $date_format] -format $date_format] $date]
}
The date format is an optional and defaulted to %Y-%m-%d. If the format is not matching then it will fail. You can handle the exceptions.
Output :
% is_valid_date "1995-02-28"
1
% is_valid_date "1995-01-35"
0
%
We are converting the date to a long and reverting to the date again. If both are not same, then the given input is incorrect.
Reference : clock

How to interpret Timelien for HighStock

I am using the HighStock API of HighChart.
The demo:
http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/stock/demo/compare/
Makes a timeline on the x-Axis.
But the data JSON data for the graph has the following keys:
E.g. for AAPL:
?(/* AAPL historical OHLC data from the Google Finance API */
[
/* Dec 2008 */
[1229472000000,12.74],
[1229558400000,12.78],
[1229644800000,12.86],
[1229904000000,12.25],
[1229990400000,12.34],
[1230076800000,12.15],
[1230249600000,12.26],
[1230508800000,12.37],
[1230595200000,12.33],
[1230681600000,12.19],
How do all the 1229.... values relate to Date/Time?? I mean how does
1232582400000
relate to 22. January 2009???
And I have data int he following format in Java:
2015-12-10 15:27
How should I use them in the HighChart API?
The numeric time stamps you see as "1232582400000" is the javascript time stamp. I believe it is UNIX epoch time in milliseconds (multiply epoch time by 1000). You can convert your human-readable time values into javascript time in any number of ways. The basic example if you have year, month, day, hour, and second would be to make your data series use Date.UTC():
[Date.UTC(year, month, day, hour, minute), yValue]
"Unix time (also known as POSIX time or Epoch time) is a system for
describing instants in time, defined as the number of seconds that
have elapsed since 00:00:00 Coordinated Universal Time (UTC),
Thursday, 1 January 1970, not counting leap seconds."
(source)

getting time in milliseconds from a date

Is it possible to take a string of date, such as 2013-02-26 10:45:54,082 and get the time in milliseconds from the "epoch" ? or something similar?
I know clock scan returns the time in seconds.
Also clock scan returns an error for this specific format.
I couldn't find something as I want, and I want to make sure it doesn't exists before I start creating it...
Thanks
The millisecond-scale offset isn't supported by Tcl (as it is a fairly rare format in practice), but you can work around that:
set str "2013-02-26 10:45:54,082"
regexp {^([^\.,]*)[\.,](\d+)$} $str -> datepart millipart; # split on the last occurrence of , or .
set timestamp [clock scan $datepart -format "%Y-%m-%d %H:%M:%S" -gmt 1]
scan $millipart "%d" millis
set millistamp [expr {$timestamp*1000 + $millis}]
(You don't supply timezone info, so I've assumed it is UTC, i.e., “GMT”. I've also allowed for using . instead of , as a millisecond separator, as which you get depends on the locale that created the time string in the first place.)

TCL Clock command

The below shown clock manipulation works well in Linux machine which has TCL 8.5. But when I use the same on the SunOS which has the TCL8.4 , I am getting the error "bad switch "-format": must be -base or -gmt".
For some reason, I am not able to upgrade my TCL 8.4 to 8.5 in SunOS.
How can I make it work in TCL 8.4 as well?
The commands are given below and what I am trying to achieve through these commands is to advance the system date by one more day.
$today contains the value "2012 06 15 14 39 20"
set today [clock scan $today -format "%Y %m %d %H %M %S"]
set tomorrow [clock add $today 86600 seconds]
set victim [clock format $tomorrow -format "%a"]
set tomorrow [clock format $tomorrow -format "%m%d%H%M"]
send "sudo date $tomorrow\r"
Jackson's answer is the core of what the issue is: 8.5 added a lot of features to clock and your code is dependent on them. However, he doesn't quite identify the best method for getting the target time.
# Multiple assignment from list
foreach {YY MM DD HH mm ss} $today break
# Get the date tomorrow in one funky step
set tomorrow [clock scan "$YY$MM$DD $HH$mm$ss + 86600 seconds"]
# Rest is the same as before
set victim [clock format $tomorrow -format "%a"]
set tomorrow [clock format $tomorrow -format "%m%d%H%M"]
send "sudo date $tomorrow\r"
(You are aware that a day is never 86600 seconds long? That's 200 seconds longer than the average length…)
As you have found out the clock command changed between Tcl 8.4 and 8.5. In 8.4 the clock scan command only recognized a number of standard formats. So you need to convert your $today value into one of these formats, see here for details.
One possible way is
regexp {(\d\d\d\d) (\d\d) (\d\d) (\d\d) (\d\d) (\d\d)} $today all YY MM DD HH mm ss
set reformatToday "$YY$MM$DD $HH$mm$ss"
set today [clock scan $reformatToday]
Tcl 8.5 will also work with this free form scan code; however this feature is deprecated in Tcl versions later than 8.4.