How to represent datetime format using EBNF - datetime

I want to know about how to represent the 'datetime' format such as "yyyy-MM-dd hh:mm" using EBNF.

One possible way of formulating this using EBNF is shown below. The expression parses only legal years, months and timestamps. However, it allows any month to have up to 31 days.
Timestamp = [ "-" ] Year "-" Month "-" Day " " Time ;
Year = Digit Digit Digit Digit ;
Month = "0" Digit | "1" "0".."2" ;
Day = "0".."2" Digit | "3" "0".."1" ;
Time = Hour ":" Minute ;
Hour = "0".."1" Digit | "2" "0".."3" ;
Minute = "0".."5" Digit ;
Digit = "0".."9" ;

Related

Is %encoded format allowed for IPv4address format of host of uri in RFC 3968?

I am trying to create a URI library from the RFC 3986 definitions. While validating host there are 3 allowed formats:
IP-literal
IPv4address
Reg-name
Here IPv4address's format is little ambiguous (or I am making a mistake in understanding that). The definition says it can be of the format: dec-octet "." dec-octet "." dec-octet "." dec-octet and
dec-octet = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
/ "25" %x30-35 ; 250-255
When the definitions says "2" %x30-34 DIGIT does it mean if any of the three digits (0-255 range number) can be represented in percent-encoded format or only some particular digits can be represented in the percent-encoded format.

File renaming based on file content in UNIX

I have pattern namely QUARTERDATE and FILENAME inside the file.
Both will have some value as in below eg.
My requirement is, I should rename the file like FILENAME_QUARTERDATE.
My file(myfile.txt) will be as below:
QUARTERDATE: 03/31/14 - 06/29/14
FILENAME : LEAD
field1 field2
34567
20.0 5,678
20.0 5,678
20.0 5,678
20.0 5,678
20.0 5,678
I want the the file name to be as LEAD_201402.txt
Date range in the file is for Quarter 2, so i given as 201402.
Thanks in advance for the replies.
newname=$(awk '/QUARTERDATE/ { split($4, d, "/");
quarter=sprintf("%04d%02d", 2000+d[3], int((d[1]-1)/3)+1); }
/FILENAME/ { fn = $3; print fn "_" quarter; exit; }' "$file")
mv "$file" "$newname"
How is a quarter defined?
As noted in comments to the main question, the problem is as yet ill-defined.
What data would appear in the previous quarter's QUARTERDATE line? Could Q1 ever start with a date in December of the previous year? Could the end date of Q2 ever be in July (or Q1 in April, or Q3 in October, or Q4 in January)? Since the first date of Q2 is in March, these alternatives need to be understood. Could a quarter ever start early and end late simultaneously (a 14 week quarter)?
To which the response was:
QUARTERDATE of Q2 will start as 1st Monday of April and end as last Sunday of June.
Which triggered a counter-response:
2014-03-31 is a Monday, but hardly a Monday in April. What this mainly means is that your definition of a quarter is, as yet, not clear. For example, next year, 2015-03-30 is a Monday, but 'the first Monday in April' is 2015-04-06. The last Sunday in March 2015 is 2015-03-29. So which quarter does the week (Mon) 2015-03-30 to (Sun) 2015-04-05 belong to, and why? If you don't know (both how and why), we can't help you reliably.
Plausible working hypothesis
The lessons of Y2K have been forgotten already (why else are two digits used for the year, dammit!).
Quarters run for an integral number of weeks.
Quarters start on a Monday and end on a Sunday.
Quarters remain aligned with the calendar quarters, rather than drifting around the year. (There are 13 weeks in 91 days, and 4 such quarters in a year, but there's a single extra day in an ordinary year and two extra in a leap year, which mean that occasionally you will get a 14-week quarter, to ensure things stay aligned.)
The date for the first date in a quarter will be near 1st January, 1st April, 1st July or 1st October, but the month might be December, March (as in the question), June or September.
The date for the last date in a quarter will be near 31st March, 30th June, 30th September, 31st December, but the month might be April, July, October or January.
By adding 1 modulo 12 (values in the range 1..12, not 0..11) to the start month, you should end up with a month firmly in the calendar quarter.
By subtracting 1 modulo 12 (values in the range 1..12 again) to the end month, you should end up with a month firmly in calendar quarter.
If the data is valid, the 'start + 1' and 'end - 1' months should be in the same quarter.
The early year might be off-by-one if the start date is in December (but that indicates Q1 of the next year).
The end year might be off-by-one if the end date is in January (but that indicates Q4 of the prior year).
More resilient code
Despite the description above, it is possible to write code that detects the quarter despite any or all of the idiosyncrasies of the quarter start and end dates. This code borrows a little from Barmar's answer, but the algorithm is more resilient to the vagaries of the calendar and the quarter start and end dates.
#!/bin/sh
awk '/QUARTERDATE/ {
split($2, b, "/")
split($4, e, "/")
if (b[1] == 12) { q = 1; y = e[3] }
else if (e[1] == 1) { q = 4; y = b[3] }
else
{
if (b[3] != e[3]) {
print "Year mismatch (" $2 " vs " $4 ") in file " FILENAME
exit 1
}
m = int((b[1] + e[1]) / 2)
q = int((m - 1) / 3) + 1
y = e[3]
}
quarter = sprintf("%.4d%.2d", y + 2000, q)
}
/FILENAME/ {
print $3 "_" quarter
# exit
}' "$#"
The calculation for m adds the start month plus one to the end month minus one and then does integer division by two. With the extreme cases already taken care of, this always yields a month number that is in the correct quarter.
The comment in front of the exit associated with FILENAME allows testing more easily. When processing each file separately, as in Barmar's example, that exit is an important optimization. Note that the error message gives an empty file name if the input comes from standard input. (Offhand, I'm not sure how to print the error message to standard error rather than standard output, other than by a platform-specific technique such as print "message" > "/dev/stderr" or print "message" > "/dev/fd/2".)
Given this sample input data (semi-plausible start and end dates for 6 quarters from 2014Q1 through 2015Q2):
QUARTERDATE: 12/30/13 - 03/30/14
FILENAME : LEAD
QUARTERDATE: 03/31/14 - 06/29/14
FILENAME : LEAD
QUARTERDATE: 06/30/14 - 09/28/14
FILENAME : LEAD
QUARTERDATE: 09/29/14 - 12/28/14
FILENAME : LEAD
QUARTERDATE: 12/29/14 - 03/29/15
FILENAME : LEAD
QUARTERDATE: 03/30/15 - 06/29/15
FILENAME : LEAD
The output from this script is:
LEAD_201401
LEAD_201402
LEAD_201403
LEAD_201404
LEAD_201501
LEAD_201502
You can juggle the start and end dates of the quarters within reason and you should still get the required output. But always be wary of calendrical calculations; they are almost invariably harder than you expect.

Numeric, alpha numeric, numeric alpha sort

I have documents within a lotus notes application that has a control number.
The control number can be either 4 digit number, alpha character and 3 digit number or 3
digit number and an alpha character.
Examples of the type of control number: 8321 or A310 or 312C
They are wanting the view to be sorted in this manner:
First 4 digit number in order
Next by Alpha & 3 digit number in order
Next by 3 digit number & alpha character
I have tried a number of things but cannot get the view to display in the manner they want
it in.
Any ideas how to do this is much appreciated.
Thank you,
Jean
Add a hidden Sort- Column before your "visible" column with the value.
Try this formula in that column (replace YourField appropriately):
_TestVal := #Text(YourField);
_firstSort := #If( #Matches( _TestVal ; "{0-9}{0-9}{0-9}{0-9}" ) ; "1";
#Matches( _TestVal ; "{A-Z}{0-9}{0-9}{0-9}" ) ; "2" ; "3" );
_secondSort := #If( _firstSort = "3" ; #Right( _TestVal ; 1) ; "0" );
_firstSort + _secondSort + _TestVal
It prepends the Value with "10", "20" or "3A" ("3B", "3C"...), depending of the #Matches and sorts the rest as Notes would by default...

Python convert military time user input and calculate time worked (datetime.timedelta)

Noob here,
I'm stuck at trying to present user input in military time into standard time. The code works so far, but I need to subtract 12 hours from the end time to display in standard time. How do I do this using datetime.time? Also, do I need to convert the original user input to an integer to perform datetime.timedelta calculations? Previous questions don't seem to answer my coding questions.
My code is:
def timeconvert():
print "Hello and welcome to Python Payroll 1.0."
print ""
# User input for start time. Variable stored.
start = raw_input("Enter your check-in time in military format (0900): ")
# User input for end time. Variable stored.
end = raw_input("Enter your check-out time in military format (1700): ")
print ""
# ---------------------------------------------------------------------------
# Present user input in standard time format hhmm = hh:mm
# ---------------------------------------------------------------------------
import datetime, time
convert_start = datetime.time(hour=int(start[0:2]), minute=int(start[2:4]))
# need to find a way to subtract 12 from the hour to present end time in standard time
convert_end = datetime.time(hour=int(end[0:2]), minute=int(end[2:4]))
print 'You started at', convert_start.strftime("%H:%M"),'am', 'and ended at', convert_end.strftime("%H:%M"), 'pm'
# ---------------------------------------------------------------------------
# Use timedelta to caculate time worked.
# ---------------------------------------------------------------------------
# print datetime.timedelta
timeconvert()
raw_input("Press ENTER to exit program") # Closes program.
Thanks.
You can use strftime("%I:%M %p") to get standard 12 hour formatting with "AM" or "PM" at the end. See the Python documentation for more details on datetime string formatting.
Also, while it is not natively supported, you can simply use the two datetime.time instances to do your calculation as part of the timedelata constructor.
The below code should suffice, though proper error checking should definitely be used. ;)
--ap
start = raw_input("Enter your check-in time in military format (0900): ")
end = raw_input("Enter your check-out time in military format (1700): ")
# convert user input to datetime instances
start_t = datetime.time(hour=int(start[0:2]), minute=int(start[2:4]))
end_t = datetime.time(hour=int(end[0:2]), minute=int(end[2:4]))
delta_t = datetime.timedelta(
hours = (end_t.hour - start_t.hour),
minutes = (end_t.minute - start_t.minute)
)
# datetime format
fmt = "%I:%M %p"
print 'You started at %s and ended at %s' % (start_t.strftime(fmt), end_t.strftime(fmt))
print 'You worked for %s' % (delta_t)
def time12hr(string):
hours = string[:2]
minutes = string[2:]
x = " "
if int(hours) == 12:
x = "p.m."
hours = "12"
elif int(hours) == 00:
x = "a.m."
hours = "12"
elif int(hours) > 12:
x = "p.m."
hours = str(int(hours) - 12)
else:
x = "a.m."
return "%s:%s %s"%(hours ,minutes,x)
print time12hr('1202')
print time12hr('1200')
print time12hr('0059')
print time12hr('1301')
print time12hr('0000')

Regular expression for asp:RegularExpressionValidator with format MMddyy (leap year issue)

We need help for regular expression that work with asp.net asp:RegularExpressionValidator to validate date in MMddyy format. Problem we are facing is leap year. Issue is that is it possible to verify through regular expression that it only accepts valid leap year dates like 02/29/2008 is a valid date but 02/29/2010 is not a valid date.
Any regular expression that works with "asp:RegularExpressionValidator"?
OK, you asked for a regex. Here it is. I think it's immediately obvious why it's not a good idea to validate a date with a regular expression:
First, the verbose, commented version to at least make understanding this beast possible:
^ # start of string
(?: # either match...
(?:
(?: # 31st day of all allowed months
(?:(?:0?[13578]|1[02])/31)
| # or
(?:(?:0?[13-9]|1[0-2])/(?:29|30))
) # 29th/30th day of any month except February
/ # plus any year since 1600
(?:1[6-9]|[2-9]\d)
\d{2}
)
| # or
(?: # match Feb 29th
0?2/29/
(?: # in all leap years since 1600
(?:
(?: # century
1[6-9]|[2-9]\d
)
(?: # two-digit years divisible by four, not ending in 00
0[48]
|
[2468][048]
|
[13579][26]
)
|
(?: # all the leap years ending in 00
(?:16|[2468][048]|[3579][26])
00
)
)
)
)
| # or
(?: # (for any month)
(?:0?[1-9])
|
(?:1[0-2])
)
/
(?: # match the 1st-28th day
0?[1-9]|1\d|2[0-8]
)
/
(?:
(?:1[6-9]|[2-9]\d)\d{2}
)
)$
Or, if you can't use verbose regexes in ASP.NET validators:
^(?:^(?:(?:(?:(?:(?:0?[13578]|1[02])/31)|(?:(?:0?[13-9]|1[0-2])/(?:29|30)))/(?:1[6-9]|[2-9]\d)\d{2})|(?:0?2/29/(?:(?:(?:1[6-9]|[2-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:(?:0?[1-9])|(?:1[0-2]))/(?:0?[1-9]|1\d|2[0-8])/(?:(?:1[6-9]|[2-9]\d)\d{2}))$)$
These allow but do not require a leading zero in single-digit months/days. If you don't want that, replace all instances of 0? with 0.
If server side is not an option, you'll have to use JavaScript. Try the code posted and explained here. It determines that 02/29/2010 is invalid and 02/29/2008 is valid. Use a CustomValidator to call the JavaScript function when necessary.
Since you need logic to validate leap years, consider using a CustomValidator. I put this together relatively quickly, but hopefully you'll get the idea.
protected void dateFormatValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
if (args.Value.Length == 6)
{
var month = args.Value.Substring(0, 2);
var day = args.Value.Substring(2, 2);
var year = args.Value.Substring(4, 2);
DateTime dummyValue;
args.IsValid = DateTime.TryParse(month + "/" + day + "/" + year, out dummyValue);
}
else
{
args.IsValid = false;
}
}
As bitwise says clientside JS is the way to do this not a horrible regex a la Tom's mindboggling post. I've got quite a tidy date validator on my work machine, I'll post on Monday.
If you ever get some kind of failed validation issue with your app can you imagine the nightmare of trying to de-cipher that regex?

Resources